كيفية جلب البيانات في React من واجهة GraphQL API: 5 طرق عملية ومقارنة تقنية

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

إذا كنت تبني تطبيقاً باستخدام React وتحتاج إلى الاتصال بواجهة GraphQL API، فهناك أكثر من أسلوب يمكن الاعتماد عليه لتحقيق ذلك بكفاءة. في هذا الدليل العملي، سنستعرض خمس طرق شائعة وفعالة لجلب البيانات، بدءاً من المكتبات المتقدمة مثل Apollo Client وurql، وصولاً إلى الحلول الأخف مثل React Query مع fetch API.

الهدف هنا ليس فقط عرض الأكواد، بل مساعدتك على فهم الفروق بين كل خيار، ومتى يكون مناسباً لمشروعك، مع الحفاظ على محتوى واضح، احترافي، وسهل التطبيق.

مقارنة أفضل الطرق لجلب البيانات في React من واجهة GraphQL API

البدء: مثال عملي باستخدام واجهة SpaceX

في الأمثلة التالية سنستخدم واجهة SpaceX GraphQL API لجلب آخر 10 عمليات إطلاق سابقة. هذا المثال مناسب لفهم الفكرة بسرعة، ويمكنك تكييفه بسهولة مع أي واجهة GraphQL أخرى داخل مشروعك.

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

1. استخدام Apollo Client في React

تُعد مكتبة Apollo Client من أشهر الأدوات للتعامل مع GraphQL داخل تطبيقات React. وتمتاز بأنها لا تقتصر على جلب البيانات من الخادم فقط، بل توفر أيضاً نظام تخزين مؤقت cache وإدارة حالة متقدمة على مستوى التطبيق.

تثبيت الحزم المطلوبة

npm install @apollo/client graphql

تهيئة العميل وربطه بالتطبيق

الفكرة الأساسية هي إنشاء كائن من ApolloClient وتزويده بعنوان نقطة النهاية uri بالإضافة إلى ذاكرة التخزين InMemoryCache، ثم تمريره إلى كامل شجرة المكونات عبر ApolloProvider.

import React from "react";
import ReactDOM from "react-dom";
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";
import App from "./App";

const client = new ApolloClient({
  uri: "https://api.spacex.land/graphql/",
  cache: new InMemoryCache()
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  rootElement
);

تنفيذ الاستعلام عبر useQuery

بعد التهيئة، يمكنك استخدام الخطاف useQuery لتنفيذ أي استعلام. كما تُستخدم الدالة gql لكتابة الاستعلام بصيغة مفهومة ومهيأة بشكل جيد داخل المحرر.

import React from "react";
import { useQuery, gql } from "@apollo/client";

const FILMS_QUERY = gql`
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, loading, error } = useQuery(FILMS_QUERY);

  if (loading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

متى تكون Apollo Client خياراً مناسباً؟

  • عندما تحتاج إلى بيئة متكاملة للتعامل مع GraphQL.
  • إذا كان مشروعك كبيراً ويعتمد على التخزين المؤقت بكثافة.
  • عندما تريد دعم الاستعلامات queries والتعديلات mutations والاشتراكات subscriptions في مكتبة واحدة.

2. استخدام urql كحل أخف من Apollo

مكتبة urql توفر تجربة قريبة من Apollo ولكن بحجم أخف وإعداد أقل. وهي مناسبة للمطورين الذين يريدون التعامل مع GraphQL بشكل منظم دون الاعتماد على مكتبة ثقيلة نسبياً.

تثبيت الحزم

npm install urql graphql

إعداد Provider وربط العميل

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { createClient, Provider } from 'urql';

const client = createClient({
  url: 'https://api.spacex.land/graphql/',
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider value={client}>
    <App />
  </Provider>,
  rootElement
);

تنفيذ الاستعلام

على خلاف Apollo، يمكن هنا كتابة الاستعلام مباشرة باستخدام template literal دون الحاجة الإلزامية إلى gql.

import React from "react";
import { useQuery } from 'urql';

const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const [result] = useQuery({
    query: FILMS_QUERY,
  });

  const { data, fetching, error } = result;

  if (fetching) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

مميزات urql

  • أخف من Apollo Client.
  • سهولة في الإعداد والبدء.
  • يوفر خطافات مشابهة لما اعتاده مطورو GraphQL في React.

3. الدمج بين React Query وgraphql-request

ليس من الضروري دائماً استخدام عميل GraphQL ضخم. أحياناً يكون الحل الأفضل هو الاعتماد على مكتبة خفيفة مثل graphql-request لتنفيذ الطلبات، مع الاستفادة من قوة React Query في إدارة حالة الخادم والتخزين المؤقت.

هذا الدمج يمنحك توازناً ممتازاً بين البساطة والمرونة.

تثبيت الحزم

npm install react-query graphql-request

إعداد QueryClientProvider

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { QueryClient, QueryClientProvider } from "react-query";

const client = new QueryClient();

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={client}>
    <App />
  </QueryClientProvider>,
  rootElement
);

تنفيذ الطلب عبر request() وuseQuery

import React from "react";
import { request, gql } from "graphql-request";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";

const FILMS_QUERY = gql`
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return request(endpoint, FILMS_QUERY);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

لماذا يُعد هذا الخيار عملياً؟

  • أقل تعقيداً من مكتبات GraphQL الكاملة.
  • يوفر تخزيناً مؤقتاً ممتازاً عبر React Query.
  • يسهّل إعادة الجلب refetch وإبطال الاستعلامات invalidate.

4. استخدام React Query مع Axios

إذا كنت تفضّل مكتبات HTTP التقليدية، فيمكنك استخدام Axios لإرسال طلب POST إلى واجهة GraphQL، ثم إدارة الحالة والذاكرة المؤقتة بواسطة React Query.

تثبيت الحزم

npm install react-query axios

تنفيذ استعلام GraphQL عبر Axios

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";
const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return axios({
      url: endpoint,
      method: "POST",
      data: { query: FILMS_QUERY }
    }).then(response => response.data.data);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

أهم ما يميز هذا النهج

  • مناسب لمن لديهم خبرة مسبقة مع Axios.
  • التعامل مع الأخطاء فيه أسهل مقارنة بـfetch.
  • يمكن دمجه بسرعة في المشاريع التي تستخدم REST وGraphQL معاً.

5. استخدام React Query مع fetch API

هذه الطريقة هي الأبسط من حيث الاعتماديات، لأن fetch API متاح افتراضياً في معظم المتصفحات الحديثة. لذلك لن تحتاج إلا إلى تثبيت react-query فقط.

تثبيت الحزمة

npm install react-query

تنفيذ الطلب عبر fetch

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";
const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ query: FILMS_QUERY })
    })
      .then((response) => {
        if (response.status >= 400) {
          throw new Error("Error fetching data");
        } else {
          return response.json();
        }
      })
      .then((data) => data.data);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

ملاحظات مهمة عند استخدام fetch

  • يجب تحديد الترويسة Content-Type بالقيمة application/json.
  • ينبغي تحويل جسم الطلب إلى نص باستخدام JSON.stringify().
  • مع fetch يجب معالجة الأخطاء يدوياً، بخلاف Axios الذي يتكفل بجزء من ذلك تلقائياً.

مقارنة سريعة بين الطرق الخمس

الطريقة مستوى التعقيد التخزين المؤقت الحجم الحالة المناسبة
Apollo Client مرتفع متقدم أكبر المشاريع الكبيرة والمعقدة
urql متوسط جيد أخف مشاريع GraphQL المرنة
React Query + graphql-request متوسط ممتاز خفيف التوازن بين البساطة والقوة
React Query + Axios منخفض إلى متوسط ممتاز متوسط لمن يستخدم Axios بالفعل
React Query + fetch منخفض ممتاز الأخف المشاريع البسيطة أو الخفيفة

كيف تختار الطريقة الأنسب لمشروعك؟

  1. إذا كنت تحتاج منظومة متكاملة لـGraphQL فاختر Apollo Client.
  2. إذا كنت تريد بديلاً أخف مع تجربة حديثة فاختر urql.
  3. إذا كنت تبحث عن حل عملي ومرن فالجمع بين React Query وgraphql-request خيار ممتاز.
  4. إذا كان مشروعك يعتمد على Axios مسبقاً، فمن المنطقي إعادة استخدامه مع React Query.
  5. إذا أردت أقل عدد ممكن من الاعتماديات، فاستخدم fetch API.

لماذا تؤثر طريقة جلب البيانات على أداء التطبيق؟

اختيارك للمكتبة أو النهج المناسب لا ينعكس فقط على تجربة المطور، بل يؤثر أيضاً على أداء التطبيق وقابليته للتوسع. فعلى سبيل المثال، توفر آليات cache الجيدة تقليل عدد الطلبات المرسلة إلى الخادم، ما يحسن السرعة ويقلل استهلاك الموارد. كما أن إدارة حالات مثل loading وerror بطريقة سليمة ترفع من جودة تجربة المستخدم النهائية.

تعلم React بشكل احترافي وفهم آليات جلب البيانات من GraphQL

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

من الناحية التقنية، لا توجد طريقة واحدة مثالية لكل مشاريع React عند التعامل مع GraphQL API. الاختيار الأفضل يعتمد على حجم التطبيق، وتعقيد البيانات، ومدى حاجتك إلى التخزين المؤقت وإدارة حالة الخادم. إذا كنت تريد حلاً مؤسسياً متكاملاً فـApollo Client يتفوق بوضوح، أما إذا كان هدفك تقليل التعقيد مع الحفاظ على كفاءة عالية، فإن الدمج بين React Query وgraphql-request يُعد من أفضل الخيارات العملية الحديثة.

اترك تعليقاً

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