Fetch vs Axios ב-React: מה ההבדל ומתי להשתמש בכל אחד?

סער טויטו

סער טויטו

Software & Web Development


כאשר אנו מפתחים אפליקציות React, ביצוע בקשות HTTP הוא אחת המשימות הנפוצות ביותר. יש לנו שתי אפשרויות עיקריות: Fetch API המובנה של הדפדפן, או ספריית Axios הפופולרית. במאמר זה נבחן את ההבדלים, נראה דוגמאות מעשיות, ונלמד מתי להשתמש בכל אחת.

מה זה Fetch API?

Fetch API הוא ממשק מובנה בדפדפנים מודרניים שמאפשר לבצע בקשות HTTP באופן אסינכרוני. הוא הוכנס כתחליף מודרני ל-XMLHttpRequest והוא זמין ללא צורך בהתקנת ספריות חיצוניות.

היתרון הגדול של Fetch הוא שהוא חינמי ולא מוסיף גודל לאפליקציה, אבל הוא דורש יותר קוד עבור משימות מתקדמות.

// Basic Fetch usage
const fetchData = async () => {
  const response = await fetch('https://api.example.com/users');
  const data = await response.json();
  return data;
};

מה זה Axios?

Axios היא ספריית JavaScript פופולרית לביצוע בקשות HTTP. היא מספקת ממשק פשוט ותכונות מתקדמות שאינן זמינות ב-Fetch באופן טבעי. Axios תומכת גם ב-Node.js וגם בדפדפן.

הספרייה מוסיפה כ-15KB לפרויקט, אבל מספקת תכונות חזקות כמו interceptors, timeout אוטומטי וטיפול משופר בשגיאות.

// Install Axios
npm install axios

// Basic usage
import axios from 'axios';

const fetchData = async () => {
  const response = await axios.get('https://api.example.com/users');
  return response.data;
};

בקשות GET

בקשות GET הן הסוג הנפוץ ביותר של בקשות HTTP והן משמשות לקבלת נתונים מהשרת. הן לא משנות מידע בשרת, רק מבקשות לקבל נתונים קיימים.

ב-Fetch אנחנו צריכים להמיר את התגובה ל-JSON ידנית, בעוד ש-Axios עושה זאת אוטומטית. זה הופך את הקוד עם Axios לקצר ופחות מועד לשגיאות.

שני הכלים תומכים ב-async/await מה שהופך את הקוד לקריא ונוח לתחזוקה, אבל יש הבדלים בכמות הקוד הנדרש.

// Fetch API
const getUsers = async () => {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    const users = await response.json();
    return users;
  } catch (error) {
    console.error('Error:', error);
  }
};
// Axios
const getUsers = async () => {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users');
    return response.data;
  } catch (error) {
    console.error('Error:', error);
  }
};

בקשות POST

בקשות POST משמשות לשליחת נתונים לשרת, בדרך כלל ליצירת משאבים חדשים או לעדכון קיימים. הן דורשות הגדרות נוספות כמו method, headers ו-body.

כאשר אנו שולחים נתונים לשרת, ההבדלים הופכים להיות יותר בולטים. Fetch דורש הגדרת headers ו-JSON.stringify ידנית, בעוד ש-Axios מטפל בכל זה באופן אוטומטי.

זה הופך את Axios לפתרון נוח יותר במיוחד כאשר יש הרבה בקשות POST באפליקציה, וחוסך קוד חוזר וטעויות פוטנציאליות.

// Fetch API - requires additional configuration
const createUser = async (userData) => {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(userData)
    });
    const result = await response.json();
    return result;
  } catch (error) {
    console.error('Error:', error);
  }
};
// Axios - much simpler
const createUser = async (userData) => {
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/users', userData);
    return response.data;
  } catch (error) {
    console.error('Error:', error);
  }
};

טיפול בשגיאות - הבדל חשוב

אחד ההבדלים הכי חשובים הוא האופן שבו מטפלים בשגיאות HTTP. Fetch לא זורק שגיאה עבור קודי סטטוס כמו 404 או 500, בעוד Axios כן.

זה אומר שעם Fetch אתם חייבים לבדוק ידנית את response.ok, בעוד ש-Axios יזרוק שגיאה אוטומטית עבור כל קוד שאינו 2xx.

// Fetch - manual status checking required
const fetchWithErrorHandling = async () => {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users/999');
    
    // Manual status check
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch Error:', error.message);
  }
};

// Axios - automatic error handling
const axiosWithErrorHandling = async () => {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users/999');
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      if (error.response) {
        console.error('Status:', error.response.status);
        console.error('Data:', error.response.data);
      } else if (error.request) {
        console.error('No response received');
      } else {
        console.error('Axios error message:', error.message);
      }
    } else {
      console.error('Non-Axios error:', error);
    }
  }
};

הגדרת Base URL וקונפיגורציה

הגדרת Base URL וקונפיגורציה גלובלית היא תכונה חשובה במיוחד עבור אפליקציות שמתקשרות עם API אחד או מספר APIs קבועים. זה מאפשר לנו להימנע מחזרה על כתובות וקונפיגורציות.

Axios מספק מנגנון מובנה וחזק להגדרת קונפיגורציה גלובלית, כולל base URL, timeouts, headers ברירת מחדל ועוד. זה הופך את הניהול של בקשות HTTP לפשוט ועקבי.

זה מאוד שימושי כאשר יש לכם API אחד עם בסיס URL קבוע, ואתם רוצים להימנע מחזרה על הכתובת בכל בקשה, וכן להוסיף headers כמו authentication באופן אוטומטי.

// Axios - Global configuration
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 10000; // 10 seconds
axios.defaults.headers.common['Authorization'] = 'Bearer token';

// Create custom instance
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token-here'
  }
});

// Usage with instance
const getUsers = () => apiClient.get('/users');
const createUser = (data) => apiClient.post('/users', data);
// Fetch - Custom wrapper function
const API_BASE = 'https://api.example.com';
const TOKEN = 'your-token-here';

const apiCall = async (endpoint, options = {}) => {
  const url = `${API_BASE}${endpoint}`;
  const config = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${TOKEN}`
    },
    ...options
  };

  const response = await fetch(url, config);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
};

Interceptors - תכונה חזקה של Axios

Interceptors מאפשרים לעבד בקשות ותגובות באופן גלובלי. זה מאוד שימושי להוספת authentication, logging או טיפול בשגיאות:

זוהי אחת התכונות החזקות ביותר של Axios - יכולת להפעיל קוד לפני שליחת כל בקשה או אחרי קבלת כל תגובה. זה מאפשר לבצע משימות כמו הוספת טוקנים, רישום (logging), או ניהול שגיאות במקום מרכזי אחד.

Request interceptors רצים לפני שליחת הבקשה ומאפשרים לשנות את ההגדרות, בעוד Response interceptors רצים אחרי קבלת התגובה ומאפשרים לעבד אותה או לטפל בשגיאות גלובליות.

// Request Interceptor - runs before every request
axios.interceptors.request.use(
  (config) => {
    // Add token to every request
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    console.log('Sending request to:', config.url);
    return config;
  },
  (error) => Promise.reject(error)
);

// Response Interceptor - runs after every response
axios.interceptors.response.use(
  (response) => {
    console.log('Received response:', response.status);
    return response;
  },
  (error) => {
    if (error.response?.status === 401) {
      // Global authentication handling
      localStorage.removeItem('authToken');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

דוגמה מעשית ב-React Component

בפיתוח React אמיתי, בקשות HTTP מבוצעות בדרך כלל בתוך components עם ניהול של loading states, שגיאות ועדכון ה-UI. זה דורש טיפול זהיר בחיי החיים של הcomponent.

הקוד מדגים איך לטעון רשימת משתמשים עם טיפול ב-loading states ובשגיאות. השימוש ב-useEffect מבטיח שהבקשה תתבצע פעם אחת בזמן הטעינה הראשונה של הcomponent.

שימו לב להבדלים בין הגישות - Axios דורש פחות קוד ופחות טיפול ידני, בעוד ש-Fetch דורש בדיקות נוספות לסטטוס ההצלחה.

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const UsersList = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  // With Axios
  const fetchUsers = async () => {
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/users');
      setUsers(response.data);
    } catch (error) {
      if (axios.isAxiosError(error)) {
        if (error.response) {
          console.error('Status:', error.response.status);
          console.error('Data:', error.response.data);
        } else if (error.request) {
          console.error('No response received');
        } else {
          console.error('Axios error message:', error.message);
        }
      } else {
        console.error('Non-Axios error:', error);
      }
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { fetchUsers(); }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
};

export default UsersList;
// Alternative with Fetch
const fetchUsers = async () => {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) throw new Error('Failed to fetch');
    const data = await response.json();
    setUsers(data);
  } catch (error) {
    console.error(error);
  } finally {
    setLoading(false);
  }
};

Timeout והגדרות נוספות

Axios מספק דרכים נוחות להגדיר timeout ואפשרויות נוספות:

Timeout חשוב למניעת בקשות תקועות שיכולות לגרום לאפליקציה להיראות לא רספונסיבית. Axios מספק דרך פשוטה להגדיר זמן קצוב, בעוד ש-Fetch דורש שימוש ב-AbortController וקוד נוסף.

זה מדגים שוב את העקרון של Axios - פתרונות מובנים לבעיות נפוצות, לעומת Fetch שדורש יישום ידני.

// Axios - simple timeout
const response = await axios.get('/api/data', { timeout: 5000 });

// Fetch - requires AbortController
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
const response = await fetch('/api/data', { signal: controller.signal });

מתי להשתמש ב-Fetch?

  • פרויקטים קטנים - כאשר לא רוצים תלויות חיצוניות
  • בקשות פשוטות - GET ו-POST בסיסיים
  • חשוב גודל Bundle - Fetch לא מוסיף גודל
  • דפדפנים מודרניים - תמיכה מעולה בדפדפנים חדשים

מתי להשתמש ב-Axios?

  • פרויקטים מורכבים - הרבה בקשות HTTP
  • צורך ב-Interceptors - authentication, logging
  • טיפול מתקדם בשגיאות - יותר פרטים על שגיאות
  • תמיכה בדפדפנים ישנים - תמיכה רחבה יותר
  • הגדרות גלובליות - base URLs, timeouts, headers

סיכום

גם Fetch וגם Axios הם כלים מעולים לביצוע בקשות HTTP ב-React. הבחירה תלויה בדרישות הפרויקט שלכם:

בחרו ב-Fetch עבור פרויקטים פשוטים שבהם גודל ה-bundle חשוב ואתם עובדים עם דפדפנים מודרניים.

בחרו ב-Axios עבור פרויקטים מורכבים שצריכים תכונות מתקדמות, טיפול משוכלל בשגיאות, או תמיכה בדפדפנים ישנים יותר.

שני הכלים יעזרו לכם לבנות אפליקציות React מהירות ואמינות - הבחירה היא עניין של התאמה לצרכים הספציפיים שלכם.