كيفية استخدام Axios مع React: دليل عملي شامل لطلبات HTTP

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

مقدمة: لماذا يعد Axios خياراً ممتازاً مع React؟

عند تطوير تطبيقات واجهات المستخدم الحديثة باستخدام React، ستحتاج غالباً إلى جلب البيانات من واجهات برمجية خارجية أو إرسال بيانات إلى خادمك الخاص. هنا يظهر دور Axios بوصفه مكتبة قوية ومرنة للتعامل مع طلبات HTTP بكفاءة وسهولة.

في هذا الدليل العملي، ستتعرّف على طريقة استخدام Axios مع React خطوة بخطوة، بدءاً من التثبيت والإعداد، مروراً بتنفيذ طلبات GET وPOST وPUT وDELETE، وصولاً إلى التعامل مع الأخطاء، وإنشاء نسخة مخصصة من Axios، واستخدام أسلوب async/await، وحتى الاستفادة من Custom Hook لتقليل التكرار وتحسين قابلية إعادة الاستخدام.

شرح استخدام Axios مع React لتنفيذ طلبات HTTP في تطبيقات الواجهة الأمامية

ما هو Axios؟

Axios هو عميل HTTP يُستخدم لإرسال الطلبات إلى نقطة نهاية محددة API Endpoint، سواء كانت واجهة برمجية خارجية أو خادماً خاصاً مبنياً باستخدام Node.js أو أي تقنية خلفية أخرى.

عندما ترسل طلباً عبر Axios، فأنت تتوقع من الواجهة البرمجية تنفيذ عملية معيّنة ثم إعادة الاستجابة المناسبة. على سبيل المثال، عند إرسال طلب GET، يكون الهدف عادةً هو استرجاع بيانات وعرضها داخل التطبيق.

مخطط يوضح إرسال طلبات HTTP عبر Axios إلى واجهة برمجية API

لماذا تستخدم Axios داخل React؟

رغم وجود أكثر من خيار لإجراء طلبات الشبكة، فإن Axios يبقى من أفضل الخيارات لعدة أسباب عملية:

  • إعدادات افتراضية مريحة مع JSON: لا تحتاج غالباً إلى ضبط الترويسات Headers يدوياً في كل مرة.
  • أسماء دوال واضحة ومتوافقة مع بروتوكول HTTP: مثل .get() و.post() و.put() و.delete().
  • تقليل حجم الكود: الوصول إلى البيانات في Axios غالباً أبسط من بدائل مثل Fetch API.
  • إدارة أفضل للأخطاء: يتعامل Axios بشكل مباشر مع أخطاء النطاق 400 و500 ويحوّلها إلى استثناءات قابلة للالتقاط.
  • قابلية الاستخدام على العميل والخادم: يمكن تشغيله داخل المتصفح وكذلك في بيئات Node.js.

كيفية إعداد Axios مع React

لبدء استخدام Axios داخل مشروع React، ستحتاج إلى:

  • مشروع React جاهز.
  • تثبيت مكتبة Axios باستخدام npm أو yarn.
  • واجهة برمجية API لإرسال الطلبات إليها.

يمكنك تثبيت المكتبة بالأمر التالي:

npm install axios

في الأمثلة التالية، سنستخدم واجهة JSON Placeholder API لاختبار عمليات قراءة البيانات وإنشائها وتحديثها وحذفها.

مسارات JSON Placeholder API وطرق HTTP المناسبة لكل عمليةعرض عملي لعمليات Axios مع React مثل الجلب والإضافة والتحديث والحذف

تنفيذ طلب GET في React

يُستخدم طلب GET لاسترجاع البيانات من الخادم. المثال التالي يجلب منشوراً واحداً من المسار /posts/1 عند تحميل المكوّن.

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts/1";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(baseURL).then((response) => {
      setPost(response.data);
    });
  }, []);

  if (!post) return null;

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

في هذا المثال، استُخدم useEffect لتنفيذ الطلب بعد تركيب المكوّن. بعد نجاح الطلب عبر axios.get()، يتم تخزين البيانات القادمة من response.data داخل الحالة state ثم عرضها في الواجهة.

ملاحظات مهمة حول طلب GET

  • البيانات المطلوبة توجد عادة داخل الخاصية response.data.
  • استخدام useEffect مناسب عند الرغبة في الجلب التلقائي عند تحميل الصفحة.
  • يمكن لاحقاً توسيع هذا النمط ليشمل حالات التحميل والخطأ.

تنفيذ طلب POST لإنشاء بيانات جديدة

إذا أردت إنشاء مورد جديد في الواجهة البرمجية، فستستخدم طلب POST. المثال التالي يرسل منشوراً جديداً عند الضغط على زر.

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function createPost() {
    axios
      .post(baseURL, {
        title: "Hello World!",
        body: "This is a new post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={createPost}>Create Post</button>
    </div>
  );
}

تعتمد الدالة createPost على .post()، حيث يتم تمرير رابط الواجهة أولاً، ثم الكائن الذي يحتوي على البيانات المراد إنشاؤها ثانياً. بعد نجاح العملية، يتم تحديث الواجهة بالبيانات المستلمة من الخادم.

تنفيذ طلب PUT لتحديث البيانات

لتحديث مورد موجود، يُستخدم طلب PUT. المثال التالي يحدّث المنشور الأول ببيانات جديدة.

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function updatePost() {
    axios
      .put(`${baseURL}/1`, {
        title: "Hello World!",
        body: "This is an updated post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={updatePost}>Update Post</button>
    </div>
  );
}

يشبه PUT إلى حد كبير POST من ناحية البنية، لكن الفرق الأساسي أنه يُستخدم لتعديل مورد موجود مسبقاً بدلاً من إنشاء مورد جديد.

تنفيذ طلب DELETE لحذف مورد

لحذف بيانات موجودة، استخدم .delete(). في كثير من الحالات، لا تحتاج إلى تمرير جسم للطلب Request Body.

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    axios.delete(`${baseURL}/1`).then(() => {
      alert("Post deleted!");
      setPost(null);
    });
  }

  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

بعد نجاح الحذف، يتم عرض تنبيه للمستخدم، ثم تُصفّر الحالة عبر تعيين post إلى null، وبذلك يختفي المحتوى من الواجهة مباشرة.

كيفية التعامل مع الأخطاء في Axios

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

لتجربة حالة الخطأ، يمكن إرسال طلب إلى مسار غير موجود مثل /posts/asdf، وهذا سيؤدي إلى استجابة تحمل الرمز 404.

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    axios
      .get(`${baseURL}/asdf`)
      .then((response) => {
        setPost(response.data);
      })
      .catch((error) => {
        setError(error);
      });
  }, []);

  if (error) return `Error: ${error.message}`;
  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

عند حدوث فشل في الطلب، لن يتم تنفيذ .then()، بل سينتقل التنفيذ إلى .catch(). ومن الأفضل دائماً حفظ الخطأ داخل state ثم عرض رسالة مفهومة للمستخدم بدلاً من ترك الواجهة في حالة غامضة.

أفضل ممارسات التعامل مع الأخطاء

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

إنشاء نسخة مخصصة من Axios

إذا كنت تستخدم نفس baseURL في طلبات متعددة، فمن الأفضل إنشاء نسخة مخصصة عبر axios.create(). هذا يجعل الكود أنظف وأسهل للصيانة.

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts"
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    client.get("/1").then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    client.delete("/1").then(() => {
      alert("Post deleted!");
      setPost(null);
    });
  }

  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

الفائدة الأساسية هنا أن client يتذكر baseURL تلقائياً، ويمكنك كذلك إضافة إعدادات موحدة أخرى مثل headers أو رموز المصادقة tokens.

استخدام async/await مع Axios

يوفر أسلوب async/await طريقة أبسط وأكثر وضوحاً لكتابة الكود مقارنةً بسلاسل .then() و.catch()، خصوصاً عندما تزداد تعقيدات التدفق البرمجي.

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts"
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    async function getPost() {
      const response = await client.get("/1");
      setPost(response.data);
    }

    getPost();
  }, []);

  async function deletePost() {
    await client.delete("/1");
    alert("Post deleted!");
    setPost(null);
  }

  if (!post) return "No post!";

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

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

متى يكون async/await أفضل؟

  • عندما تكون لديك عدة طلبات متسلسلة.
  • عندما تريد كتابة كود أقرب إلى الأسلوب المتزامن Synchronous.
  • عندما تحتاج إلى تنظيم أفضل للأخطاء باستخدام try/catch.

إنشاء Custom Hook باستخدام useAxios

إذا كنت ترغب في تبسيط جلب البيانات أكثر، فيمكنك الاستفادة من Custom Hook جاهز مثل useAxios من مكتبة use-axios-client. هذا الخيار يساعد على تقليل التكرار وجعل منطق جلب البيانات أكثر أناقة.

ثبّت الحزمة أولاً:

npm install use-axios-client

ثم استخدمها على النحو التالي:

import { useAxios } from "use-axios-client";

export default function App() {
  const { data, error, loading } = useAxios({
    url: "https://jsonplaceholder.typicode.com/posts/1"
  });

  if (loading || !data) return "Loading...";
  if (error) return "Error!";

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  );
}

تعيد هذه الخطاف Hook ثلاث حالات مهمة:

  • loading لمعرفة ما إذا كان الطلب ما يزال قيد التنفيذ.
  • error لمعالجة الفشل عند حدوثه.
  • data لعرض البيانات بعد وصولها بنجاح.

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

مقارنة سريعة بين أشهر استخدامات Axios

العملية الدالة الاستخدام
جلب البيانات .get() استرجاع مورد أو مجموعة موارد
إنشاء بيانات .post() إضافة مورد جديد
تحديث كامل .put() استبدال بيانات مورد موجود
حذف مورد .delete() إزالة مورد من الخادم

نصائح عملية لكتابة كود أنظف مع Axios وReact

  1. أنشئ نسخة مخصصة عند تكرار نفس baseURL.
  2. اعزل منطق الطلبات المعقدة في ملفات خدمات services مستقلة.
  3. استخدم async/await عندما يزداد تعقيد التسلسل البرمجي.
  4. وفّر رسائل تحميل وأخطاء واضحة لتحسين تجربة المستخدم.
  5. تأكد من تغليف المصطلحات البرمجية داخل code للحفاظ على اتجاه النص داخل المحتوى العربي.

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

Axios ليس مجرد أداة لجلب البيانات، بل هو طبقة عملية تنظّم اتصال تطبيق React مع الواجهات البرمجية بصورة أوضح وأكثر قابلية للصيانة. إذا كان مشروعك يحتاج إلى كود مرن، وإدارة أفضل للأخطاء، وصياغة أبسط لطلبات HTTP، فإن اعتماد Axios يُعد قراراً تقنياً موفقاً. ومع دمجه مع async/await أو Custom Hooks، يمكنك بناء بنية نظيفة وقابلة للتوسع دون تعقيد غير ضروري.

اترك تعليقاً

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