GraphQL للمطورين في الواجهة الأمامية: دليل عملي للبدء باستخدام Apollo Client وReact

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

مقدمة: لماذا يهتم مطور الواجهة الأمامية بـ GraphQL؟

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

في هذا الدليل العملي، سنشرح أساسيات GraphQL بلغة واضحة، ثم ننتقل إلى تطبيق بسيط باستخدام React وApollo Client لبناء تطبيق يعرض قائمة من أعمال anime.

مقدمة تعليمية حول GraphQL للمطورين في الواجهة الأمامية

ما هو GraphQL؟

GraphQL هو query language يُستخدم للتواصل مع API بطريقة تتيح للتطبيق طلب البيانات التي يحتاجها فقط، بالشكل الذي يريده بالضبط. وهذا يختلف عن كثير من واجهات REST التقليدية التي قد تعيد بيانات أكثر أو أقل من المطلوب.

الميزة الجوهرية في GraphQL هي أن العميل يحدد:

  • ما هي الحقول المطلوبة.
  • كيف يجب أن تكون بنية الاستجابة.
  • أي كيان أو علاقة يحتاج إلى قراءتها من الخادم.

المشكلة التي يحلها GraphQL

يعالج GraphQL مشكلتين شائعتين في جلب البيانات:

  • Over Fetching: عندما يحصل التطبيق على بيانات كثيرة لا يحتاج إليها فعلياً.
  • Under Fetching: عندما لا يحصل التطبيق على كل البيانات المطلوبة، فيضطر إلى تنفيذ طلبات إضافية.

على سبيل المثال، إذا كنت تريد فقط عرض userName وuserImage وName داخل صفحة الملف الشخصي، لكن الواجهة البرمجية ترسل مع ذلك تفاصيل أخرى كثيرة غير مستخدمة، فأنت هنا أمام حالة Over Fetching.

أما إذا أرسلت الواجهة البرمجية جزءاً ناقصاً من البيانات، واضطررت إلى تنفيذ طلب آخر لاستكمال الحقول اللازمة، فهذه حالة Under Fetching.

مثال توضيحي لمشكلة Under Fetching عند جلب البيانات من API

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

رسم يوضح كفاءة GraphQL في تقليل جلب البيانات الزائد أو الناقص

كيف تبدأ مع GraphQL؟

قبل بناء أي مشروع فعلي، من المهم التعرف إلى بعض المفاهيم الأساسية والأدوات التي تسهّل تجربة التطوير.

GraphQL Playground

GraphQL Playground عبارة عن بيئة رسومية تفاعلية تساعدك على استكشاف الخادم وتنفيذ الاستعلامات بسهولة. يمكنك من خلالها تجربة queries المختلفة ومعاينة النتائج مباشرة.

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

واجهة GraphQL Playground لتجربة الاستعلامات واختبار النتائج

عند الضغط على زر التشغيل، يتم تنفيذ الاستعلام وعرض النتيجة فوراً.

كيف نطلب البيانات أو نرسلها في GraphQL؟

في GraphQL نستخدم:

  • query لقراءة البيانات.
  • mutation لإضافة البيانات أو تعديلها أو حذفها.

الصيغة الأساسية لأي عملية تكون كالتالي:

GraphQLOperatoinType Name {
....
........
.....
...
}

أما الاستعلام البسيط فيُكتب بهذه الصورة:

query getData {
  ...
}

وبالمثل، إذا أردت تنفيذ عملية كتابة بيانات، يمكنك استبدال query بـ mutation.

استكشاف البيانات باستخدام Apollo Studio

بعد تجربة GraphQL Playground، ستجد أن Apollo Studio يوفر تجربة أكثر سلاسة، خاصة لمطور الواجهة الأمامية. فمن خلاله يمكنك اختيار الحقول المطلوبة من الواجهة الرسومية، ليقوم بإنشاء الاستعلام تلقائياً.

كل ما عليك فعله هو تحديد الحقول من الجهة اليسرى، وستحصل على query جاهز يمكنك نسخه مباشرة إلى مشروعك.

واجهة Apollo Studio لإنشاء استعلامات GraphQL بصرياً

بناء تطبيق Anime بسيط باستخدام GraphQL وReact

سنستخدم في هذا المثال Anilist API للحصول على قائمة من أعمال anime. التطبيق سيكون مبنياً باستخدام React، لكن الفكرة نفسها قابلة للتطبيق في أي مكتبة أو إطار عمل آخر.

إنشاء مشروع React جديد

ابدأ بإنشاء مشروع جديد عبر الأمر التالي:

npx create-react-app graphql-example

بعد إنشاء المشروع، انتقل إلى المجلد وثبّت الحزم المطلوبة:

npm install graphql @apollo/client

إعداد Apollo Client

الخطوة التالية هي إعداد Apollo Client داخل الملف src/index.js. قم أولاً باستيراد الأدوات الأساسية:

import {ApolloClient, InMemoryCache, ApolloProvider} from '@apollo/client' ;

ApolloClient هو الكائن المسؤول عن إدارة الاتصال مع خادم GraphQL. عند إنشائه، نحتاج عادة إلى أمرين أساسيين:

  • uri: عنوان خادم GraphQL.
  • cache: آلية تخزين مؤقت تساعد على تقليل الطلبات وتحسين الأداء.

ويكون الإعداد على النحو التالي:

const client = new ApolloClient({
  uri : 'https://graphql.anilist.co/' ,
  cache : new InMemoryCache(),
})

بعد ذلك، اجعل هذا العميل متاحاً لجميع مكونات التطبيق عبر تغليف المكون الأعلى بـ ApolloProvider.

كتابة أول Query

الآن بعد اكتمال الإعداد الأولي، حان وقت تنفيذ أول استعلام. سنستخدم useQuery لجلب البيانات، لكن قبل ذلك علينا تعريف الاستعلام باستخدام gql.

قم أولاً باستيراد الأداتين:

import {useQuery, gql} from '@apollo/client' ;

ثم عرّف الاستعلام بالشكل التالي:

const AnimeList = gql `
 query Query {
  Page {
   media {
    siteUrl
    title {
     english
     native
    }
    description
    coverImage {
     medium
    }
    bannerImage
    volumes
    episodes
   }
  }
 }
` ;

جلب البيانات باستخدام useQuery

بعد تعريف الاستعلام، يمكنك تنفيذه مباشرة باستخدام useQuery:

const {loading, error, data} = useQuery(AnimeList);

تُرجع هذه الدالة ثلاث حالات مهمة:

  • loading: لمعرفة ما إذا كان الطلب لا يزال قيد التنفيذ.
  • error: لمعالجة الأخطاء المحتملة.
  • data: للوصول إلى البيانات عند نجاح الطلب.

وللتحقق من عمل التطبيق في البداية، يمكن عرض البيانات بشكل خام:

if (loading) return ( <> Loading </> );
if (error) return ( <> {JSON.stringify(error)} </> )

return ( <> {JSON.stringify(data)} </> );

عرض بيانات GraphQL الخام داخل تطبيق React للتحقق من نجاح الطلب

تنسيق واجهة التطبيق وعرض قائمة Anime

بعد التأكد من وصول البيانات، يمكننا عرضها بشكل أكثر أناقة. ومن الأفضل هنا استخدام optional chaining لتفادي الأخطاء الناتجة عن القيم غير الجاهزة أثناء التحميل.

<div className= "container" >
  < h1 > 🐈 Anime List </ h1 >
  < hr width = "80%" />
  {data?.Page?.media.map( anime => (
    <>
      < div className = "card" >
        < img src = {anime.coverImage.medium}/ >
        < div >
          < h1 > {anime.title.english} </ h1 >
          < div className = "episodes" >
            Episodes < b > {anime.episodes} </ b >
          </ div >
          < div dangerouslySetInnerHTML = {{__html: anime.description }} > </ div >
        </ div >
      </ div >
      < hr width = "75%" />
    </>
  ))}
  <div className= "buttonContainer" >
    { page != 1 && < button > Previous Page </ button > }
    <div className= "pageText" >{page}</div>
    <button onClick = {NextPage} > Next Page </ button >
  </div>
</div>);

واجهة تطبيق Anime بسيطة بعد تنسيق البيانات القادمة من GraphQL

التعامل مع Variables في GraphQL

حتى الآن نحن نجلب صفحة واحدة فقط من النتائج. لكن ماذا لو أردنا الانتقال بين الصفحات؟ هنا يأتي دور variables في GraphQL.

من خلال Apollo Studio يمكنك إضافة متغير page بسهولة عبر قسم arguments داخل المسار root > query > page.

إضافة متغير page داخل Apollo Studio لاستخدام pagination في GraphQL

عند النقر على page سيُضاف المتغير إلى الاستعلام، ويمكنك تغيير قيمته من قسم variables لمعاينة نتائج صفحات مختلفة.

تعديل قيمة متغير page داخل Apollo Studio لتجربة صفحات متعددة

تمرير المتغيرات داخل التطبيق

داخل تطبيق React سنستخدم useState لتتبع الصفحة الحالية، ثم نمرر القيمة إلى useQuery.

const [page, setPage] = useState( 1 );

//this is how we would be passing the page in the query.
const {loading, error, data} = useQuery(AnimeList , {
  variables : { "page" : page }
});

const NextPage = () => {
  setPage(page+ 1 );
}

const PreviousPage = () => {
  setPage(page - 1 );
}

<div className= "buttonContainer" >
  { page != 1 && < button onClick = {PreviousPage} > Previous Page </ button > }
  <div className= "pageText" >{page}</div>
  <button onClick = {NextPage} > Next Page </ button >
</div>

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

مزايا GraphQL لمطوري Front End

بعد هذا المثال العملي، يمكن تلخيص أهم فوائد GraphQL لمطوري الواجهة الأمامية في النقاط التالية:

  • تقليل البيانات غير الضرورية المرسلة من الخادم.
  • الحصول على استجابة مصممة وفق احتياجات الواجهة فقط.
  • تقليل عدد الطلبات في الحالات التي تتطلب بيانات مترابطة.
  • تجربة تطوير أفضل بفضل أدوات مثل Apollo Studio وGraphQL Playground.
  • سهولة إدارة البيانات في تطبيقات React عبر Apollo Client.

أفضل ممارسات عند استخدام GraphQL في المشاريع الحقيقية

1. لا تطلب إلا ما تحتاجه

رغم أن GraphQL يمنحك حرية تحديد الحقول، فإن بعض المطورين يقعون في خطأ طلب حقول كثيرة لمجرد أنها متاحة. الأفضل دائماً هو الالتزام بالحد الأدنى المطلوب للواجهة.

2. استفد من التخزين المؤقت

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

3. راقب معالجة الأخطاء

ينبغي عرض رسائل مناسبة للمستخدم عند حدوث فشل في الطلب، وعدم الاكتفاء بطباعة الخطأ تقنياً فقط، خاصة في التطبيقات الإنتاجية.

4. نظّف المحتوى المعروض من API

في المثال السابق استُخدم dangerouslySetInnerHTML لعرض الوصف. هذه الطريقة مفيدة أحياناً، لكنها تتطلب حذراً شديداً عند التعامل مع محتوى HTML لتجنب الثغرات الأمنية.

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

GraphQL ليس مجرد بديل تقني عن REST، بل هو أسلوب أكثر ذكاءً في إدارة تدفق البيانات بين الواجهة الأمامية والخادم. بالنسبة لمطور Front End، تكمن قيمته الحقيقية في القدرة على بناء واجهات أسرع وأكثر دقة، مع تقليل الهدر في الطلبات وتحسين تجربة التطوير. وعند دمجه مع Apollo Client وReact، يصبح من السهل إنشاء تطبيقات حديثة مرنة وقابلة للتوسع، خاصة عندما تكون بنية البيانات معقدة أو متغيرة باستمرار.

اترك تعليقاً

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