شرح واجهة Giphy API: إنشاء صور GIF نصية متحركة باستخدام ReactJS
مقدمة: لماذا استخدام Giphy API مع ReactJS؟
في هذا الدليل العملي، ستتعرف على طريقة بناء تطبيق بسيط وفعّال باستخدام ReactJS لتوليد صور GIF نصية متحركة بالاعتماد على Giphy API. الفكرة الأساسية تقوم على استقبال نص من المستخدم، ثم إرساله إلى الواجهة البرمجية، وبعدها عرض النتائج داخل واجهة التطبيق بشكل منظم وسهل التصفح.
هذا النوع من المشاريع مناسب للتعلّم وبناء نماذج قابلة للتطوير، كما أنه يوضح كيفية التعامل مع API خارجي، وإدارة الحالة داخل React، وعرض البيانات الديناميكية بأسلوب عملي.

بدء العمل: المتطلبات الأساسية
قبل كتابة أي سطر برمجي، ستحتاج إلى بيئة تطوير جاهزة لمشاريع ReactJS. يمكن البدء بسهولة عبر create-react-app لأنه يوفّر هيكل مشروع مناسب للتجارب السريعة والتطبيقات التعليمية.
بعد ذلك، توجّه إلى بوابة المطورين الخاصة بـ Giphy وأنشئ حساباً جديداً للحصول على مفتاح API Key. بعد تسجيل الدخول، ستظهر لك لوحة تحكم المطور.
من داخل اللوحة، انقر على خيار Create an App ثم اختر نوع SDK المناسب. بعد إتمام الخطوات، ستحصل على مفتاح API الذي سيُستخدم لإرسال الطلبات إلى Giphy API.
إعداد ملفات المشروع ومجلداته
هيكل المشروع هنا تقليدي ومناسب لمعظم تطبيقات ReactJS. داخل مجلد src، أنشئ مجلداً باسم components ثم أضف الملفين Error.js وTextList.js.
ستحتاج أيضاً إلى ملف .env في جذر المشروع لتخزين مفتاح API بعيداً عن الشيفرة المباشرة. من المهم أن يبدأ اسم المتغير بالمقدمة REACT_APP_ حتى يتمكن React من قراءته:
REACT_APP_GIPHY_KEY=apikeyhere
هذا الأسلوب أفضل من كتابة المفتاح مباشرة داخل الكود، خاصة عند نشر المشروع أو العمل ضمن فريق.
تثبيت مكتبة Giphy JS Fetch
لتسهيل التواصل مع الواجهة البرمجية، استخدم المكتبة الرسمية المساعدة من Giphy عبر الأمر التالي:
npm install @giphy/js-fetch-api
إرسال أول طلب إلى Giphy API
الخطوة الأولى في التطبيق هي إنشاء حقل إدخال ليستقبل النص المطلوب تحويله إلى GIF متحرك. بعد إدخال النص، سنرسل هذا النص إلى API ثم نحفظ النتائج في حالة التطبيق.
ضع الشيفرة التالية داخل ملف App.js:
import { GiphyFetch } from '@giphy/js-fetch-api'
import {useState} from 'react'
import TextList from './components/TextList'
import Error from './components/Error'
import './App.css'
;
const giphy = new GiphyFetch(process.env.REACT_APP_GIPHY_KEY)
function App ( ) {
const [text, setText] = useState( '' )
const [results, setResults] = useState([])
const [err, setErr] = useState( false )
const handleInput = ( e ) => {
setText(e.target.value)
}
const handleSubmit = ( e ) => {
if (text.length === 0 ) {
//set error state to true
setErr( true )
return
}
console .log(text)
const apiCall = async () => {
const res = await giphy.animate(text, { limit : 20 })
console .log(res.data)
setResults(res.data)
}
apiCall()
setText( '' )
setErr( false )
}
return (
< div className = "App" >
< h1 > Animated Text Generator </ h1 >
< h3 > Type text into the form and hit submit </ h3 >
< input className = 'input-field' value = {text} onChange = {handleInput} />
< button className = 'submit-btn' onClick = {handleSubmit} > Submit </ button >
</ div >
);
}
export default App;
شرح ما يحدث داخل الشيفرة
- يتم إنشاء كائن
giphyعبرnew GiphyFetch(process.env.REACT_APP_GIPHY_KEY)، وهو المسؤول عن تنفيذ الطلبات إلىGiphy API. - يتم جلب المفتاح من ملف
.envباستخدامprocess.env.REACT_APP_GIPHY_KEY. - الحالة
textتخزّن قيمة الإدخال التي يكتبها المستخدم. - الحالة
resultsتحفظ البيانات المسترجعة منAPI. - الحالة
errتستخدم لعرض رسالة خطأ عند محاولة الإرسال بدون نص. - الدالة
handleInputتحدّث قيمة الإدخال بشكل فوري. - الدالة
handleSubmitتتحقق من صحة الإدخال، ثم تستدعيgiphy.animate()لإرجاع النتائج.
عند تشغيل التطبيق وفحص وحدة التحكم في المتصفح، يفترض أن ترى مصفوفة تحتوي على 20 عنصراً تمثل النتائج المسترجعة من Giphy.
عرض البيانات في React باستخدام مكونات منفصلة
بعد التأكد من وصول البيانات وحفظها في الحالة، ننتقل إلى مرحلة العرض داخل الواجهة. لتحقيق تنظيم أفضل، سنستخدم مكوّنين منفصلين: مكوّن لرسائل الخطأ ومكوّن لعرض قائمة الصور.
إنشاء مكوّن الخطأ Error.js
أضف الشيفرة التالية داخل الملف Error.js:
const Error = ( props ) => {
if (!props.isError) {
return null
}
return (
< p className = 'error' > {props.text} </ p >
)
}
export default Error
هذا المكوّن بسيط جداً؛ فإذا كانت الخاصية isError تساوي true، فسيتم عرض النص المرسل في الخاصية text. أما إذا كانت قيمتها false، فسيعيد null ولن يظهر أي شيء على الشاشة.
إنشاء مكوّن عرض الصور TextList.js
الآن أضف الشيفرة التالية إلى الملف TextList.js:
const TextList = ( props ) => {
const items = props.gifs.map( ( itemData ) => {
return <Item url = {itemData.url} />
});
return <div className = "text-container" > {items} </div>
};
const Item = ( props ) => {
return (
<div className = "gif-item">
<img src = {props.url} />
</div>
);
};
export default TextList;
هذا المكوّن يتعامل مع النتائج القادمة من API على النحو التالي:
- المصفوفة
gifsتُمرَّر من المكوّن الرئيسي. - يتم استخدام
map()للمرور على كل عنصر داخل المصفوفة. - كل عنصر ينتج عنه مكوّن
Itemيعرض صورة من خلال الخاصيةurl. - تُجمع العناصر داخل حاوية تحمل الفئة
text-containerلتسهيل تنسيقها لاحقاً.
ربط المكونات داخل الملف الرئيسي App.js
بعد تجهيز المكونات الفرعية، أصبح من السهل استخدامها داخل الواجهة الرئيسية. إليك النسخة النهائية من ملف App.js:
import TextList from './components/TextList'
import Error from './components/Error'
import { GiphyFetch } from '@giphy/js-fetch-api'
import {useState} from 'react'
import './App.css'
;
const giphy = new GiphyFetch(process.env.REACT_APP_GIPHY_KEY)
function App ( ) {
const [text, setText] = useState( '' )
const [results, setResults] = useState([])
const [err, setErr] = useState( false )
const handleInput = ( e ) => {
setText(e.target.value)
}
const handleSubmit = ( e ) => {
if (text.length === 0 ) {
//set error state to true
setErr( true )
return
}
console .log(text)
const apiCall = async () => {
const res = await giphy.animate(text, { limit : 20 })
setResults(res.data)
}
apiCall()
//change error state back to false
setText( '' )
setErr( false )
}
return (
< div className = "App" >
< h1 > Animated Text Generator </ h1 >
< h3 > Type text into the form and hit submit </ h3 >
< input className = 'input-field' value = {text} onChange = {handleInput} />
< button className = 'submit-btn' onClick = {handleSubmit} > Submit </ button >
< Error isError = {err} text = 'need length longer than 0 for input' />
{results && < TextList gifs = {results} /> }
</ div >
);
}
export default App;
ماذا أضفنا هنا؟
- تم تمرير الحالة
errإلى المكوّنErrorلعرض رسالة مخصّصة عند وجود خطأ. - تم استخدام العرض الشرطي عبر العامل
&&لإظهار المكوّنTextListفقط عند وجود نتائج.
بهذه الطريقة، لن يتم عرض الحاوية الخاصة بالصور إلا بعد نجاح الاستجابة من API ووصول البيانات فعلياً.
إضافة تنسيق CSS لتحسين الواجهة
التطبيق الآن يعمل من الناحية الوظيفية، لكن المظهر لا يزال بحاجة إلى بعض التحسين. أضف التنسيقات التالية داخل الملف App.css:
.App {
text-align : center;
}
.error {
color : #b50000 ;
font-size : 20px ;
font-weight : 500 ;
}
.input-field {
font-size : 20px ;
vertical-align : middle;
transition : .5s ;
border-width : 2px ;
margin : 5px ;
}
.input-field:focus {
box-shadow : 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
outline : none;
}
.input-field:hover {
box-shadow : 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
}
.submit-btn {
background-color : rgb(19, 209, 235);
color : #fff ;
padding : 6px 30px ;
vertical-align : middle;
outline : none;
border : none;
font-size : 16px ;
transition : .3s ;
cursor : pointer;
}
.submit-btn:hover {
background-color : rgb(10, 130, 146);
}
.text-container {
display : flex;
flex-wrap : wrap;
justify-content : center;
}
.gif-item {
flex-basis : 19% ;
}
img {
max-width : 100% ;
}
@media screen and (max-width: 992px) {
.gif-item {
flex-basis : 31% ;
}
}
@media screen and (max-width: 600px) {
.gif-item {
flex-basis : 48% ;
}
}
هذه التنسيقات تضيف تحسينات بصرية أساسية مثل:
- محاذاة العناصر في منتصف الصفحة.
- إبراز رسائل الخطأ بلون واضح.
- إضافة تأثيرات تفاعلية إلى حقل الإدخال والزر.
- عرض الصور داخل شبكة مرنة باستخدام
flexbox. - ضبط عدد الأعمدة تلقائياً حسب حجم الشاشة عبر
media queries.
ميزات أخرى مفيدة في Giphy API
ميزة النصوص المتحركة ليست سوى جزء من الإمكانات التي توفرها Giphy API. فيما يلي بعض الخصائص الأخرى التي يمكن توظيفها في مشاريع عملية.
واجهة Animated Emoji
هذه الواجهة تعيد مجموعة من رموز Emoji المتحركة دون الحاجة إلى تمرير معلمات معقدة. مثال بسيط:
const data = await gf.emoji()
يمكن أن تكون هذه الميزة مناسبة جداً عند بناء تطبيق دردشة أو منصة تواصل تحتاج إلى إدراج رموز متحركة بسهولة داخل الرسائل.
مكونات واجهة جاهزة من Giphy
إذا كنت لا ترغب في بناء كل شيء يدوياً، فإن Giphy توفّر مكونات جاهزة لـ ReactJS وJavaScript التقليدي. هذه المكونات تختصر عليك وقتاً كبيراً، خاصة عند عرض شبكة من الصور المتحركة.
import { Grid } from '@giphy/react-components'
import { GiphyFetch } from '@giphy/js-fetch-api'
// use @giphy/js-fetch-api to fetch gifs
// apply for a new Web SDK key. Use a separate key for every platform (Android, iOS, Web)
const gf = new GiphyFetch('your Web SDK key')
// fetch 10 gifs at a time as the user scrolls (offset is handled by the grid)
const fetchGifs = ( offset: number ) => gf.trending({ offset, limit : 10 })
// React Component
ReactDOM.render(
<Grid width = {800} columns = {3} gutter = {6} fetchGifs = {fetchGifs} />,
target
)
الميزة المهمة هنا أن المكوّن Grid يدعم التحميل التدريجي للمحتوى عند تمرير الصفحة، ما يمنح تجربة استخدام أفضل دون الحاجة إلى كتابة منطق إضافي معقّد.
واجهة Trending API
هذه الواجهة تعيد محتوى رائجاً يتم تحديثه باستمرار بناءً على تفاعل المستخدمين وما يلقى انتشاراً داخل منصة Giphy. وهي مناسبة للتطبيقات التي تعتمد على اكتشاف المحتوى الشائع تلقائياً.
واجهة Search API
تعمل هذه الواجهة بطريقة شبيهة بواجهة النصوص المتحركة، لكنك ترسل استعلام بحث بدلاً من نص لتحويله إلى حركة. النتيجة تكون مصفوفة من صور GIF المطابقة للكلمة المفتاحية أو العبارة المطلوبة.
وبالطبع، هناك واجهات إضافية كثيرة يمكن استكشافها من خلال توثيق Giphy API الرسمي، ما يمنحك مساحة كبيرة لتطوير أفكار متنوعة.
أفضل ممارسات لتحسين المشروع تقنياً
- أضف معالجة أخطاء باستخدام
try...catchلتفادي انهيار الواجهة عند فشل الطلب. - استخدم مؤشر تحميل مثل
loading stateلإعلام المستخدم بأن النتائج قيد الاسترجاع. - احرص على إضافة الخاصية
altللصور عندما يكون ذلك متاحاً لتحسين الوصول وتجربة المستخدم. - فكّر في تقييد عدد الطلبات أو تأخير الإرسال باستخدام
debounceإذا أردت تطوير التجربة لاحقاً. - لا تضع مفاتيح الإنتاج الحساسة في الواجهة الأمامية دون فهم حدود الأمان الخاصة بالمشروع.
الخلاصة التقنية
يوضح هذا المشروع كيف يمكن دمج ReactJS مع Giphy API لبناء تطبيق تفاعلي بسيط لكن غني من ناحية التعلم العملي. من الناحية التقنية، أفضل ما في هذا المثال أنه يجمع بين إدارة الحالة، واستهلاك API خارجي، وتقسيم الواجهة إلى مكونات قابلة لإعادة الاستخدام. وإذا أضفت لاحقاً تحسينات مثل معالجة الأخطاء، ومؤشرات التحميل، وتحسين الأداء، فسيصبح لديك نموذج قوي يمكن البناء عليه في مشاريع أكثر احترافية.