شرح واجهة Giphy API: إنشاء صور GIF نصية متحركة باستخدام ReactJS

دقائق القراءة: 9

مقدمة: لماذا استخدام Giphy API مع ReactJS؟

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

هذا النوع من المشاريع مناسب للتعلّم وبناء نماذج قابلة للتطوير، كما أنه يوضح كيفية التعامل مع API خارجي، وإدارة الحالة داخل React، وعرض البيانات الديناميكية بأسلوب عملي.

شرح استخدام Giphy API لإنشاء صور GIF نصية متحركة باستخدام ReactJS

بدء العمل: المتطلبات الأساسية

قبل كتابة أي سطر برمجي، ستحتاج إلى بيئة تطوير جاهزة لمشاريع ReactJS. يمكن البدء بسهولة عبر create-react-app لأنه يوفّر هيكل مشروع مناسب للتجارب السريعة والتطبيقات التعليمية.

بعد ذلك، توجّه إلى بوابة المطورين الخاصة بـ Giphy وأنشئ حساباً جديداً للحصول على مفتاح API Key. بعد تسجيل الدخول، ستظهر لك لوحة تحكم المطور.

لوحة تحكم مطوري Giphy للحصول على مفتاح API

من داخل اللوحة، انقر على خيار 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.

نتائج استجابة Giphy API داخل وحدة تحكم المتصفح

عرض البيانات في 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 يدعم التحميل التدريجي للمحتوى عند تمرير الصفحة، ما يمنح تجربة استخدام أفضل دون الحاجة إلى كتابة منطق إضافي معقّد.

مكونات واجهة جاهزة من Giphy لعرض صور GIF داخل التطبيقات

واجهة Trending API

هذه الواجهة تعيد محتوى رائجاً يتم تحديثه باستمرار بناءً على تفاعل المستخدمين وما يلقى انتشاراً داخل منصة Giphy. وهي مناسبة للتطبيقات التي تعتمد على اكتشاف المحتوى الشائع تلقائياً.

واجهة Search API

تعمل هذه الواجهة بطريقة شبيهة بواجهة النصوص المتحركة، لكنك ترسل استعلام بحث بدلاً من نص لتحويله إلى حركة. النتيجة تكون مصفوفة من صور GIF المطابقة للكلمة المفتاحية أو العبارة المطلوبة.

وبالطبع، هناك واجهات إضافية كثيرة يمكن استكشافها من خلال توثيق Giphy API الرسمي، ما يمنحك مساحة كبيرة لتطوير أفكار متنوعة.

أفضل ممارسات لتحسين المشروع تقنياً

  • أضف معالجة أخطاء باستخدام try...catch لتفادي انهيار الواجهة عند فشل الطلب.
  • استخدم مؤشر تحميل مثل loading state لإعلام المستخدم بأن النتائج قيد الاسترجاع.
  • احرص على إضافة الخاصية alt للصور عندما يكون ذلك متاحاً لتحسين الوصول وتجربة المستخدم.
  • فكّر في تقييد عدد الطلبات أو تأخير الإرسال باستخدام debounce إذا أردت تطوير التجربة لاحقاً.
  • لا تضع مفاتيح الإنتاج الحساسة في الواجهة الأمامية دون فهم حدود الأمان الخاصة بالمشروع.

الخلاصة التقنية

يوضح هذا المشروع كيف يمكن دمج ReactJS مع Giphy API لبناء تطبيق تفاعلي بسيط لكن غني من ناحية التعلم العملي. من الناحية التقنية، أفضل ما في هذا المثال أنه يجمع بين إدارة الحالة، واستهلاك API خارجي، وتقسيم الواجهة إلى مكونات قابلة لإعادة الاستخدام. وإذا أضفت لاحقاً تحسينات مثل معالجة الأخطاء، ومؤشرات التحميل، وتحسين الأداء، فسيصبح لديك نموذج قوي يمكن البناء عليه في مشاريع أكثر احترافية.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *