Как использовать Axios в React?react-87

1. Установка и базовый пример

npm install axios
# или
yarn add axios

Базовый GET-запрос в функциональном компоненте:

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

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    axios.get('https://api.example.com/users')
      .then(response => {
        setUsers(response.data);
        setLoading(false);
      })
      .catch(error => {
        setError(error);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

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

2. Создание экземпляра Axios

Рекомендуется создавать настроенный экземпляр для всего приложения:

// src/api/axiosConfig.js
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  }
});

// Добавляем интерсептор для JWT-авторизации
apiClient.interceptors.request.use(config => {
  const token = localStorage.getItem('authToken');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

export default apiClient;

3. CRUD операции

GET

apiClient.get('/users')
  .then(response => console.log(response.data))
  .catch(error => console.error(error));

POST

apiClient.post('/users', { name: 'John Doe' })
  .then(response => console.log('Created:', response.data));

PUT/PATCH

// Полное обновление
apiClient.put('/users/1', { name: 'Updated Name' });

// Частичное обновление
apiClient.patch('/users/1', { email: 'new@email.com' });

DELETE

apiClient.delete('/users/1')
  .then(() => console.log('User deleted'));

4. Работа с хуками

Кастомный хук для запросов:

// src/hooks/useApi.js
import { useState, useEffect } from 'react';
import apiClient from '../api/axiosConfig';

function useApi(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await apiClient.get(url);
        setData(response.data);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error, refetch: fetchData };
}

export default useApi;

Использование хука в компоненте:

function Products() {
  const { data: products, loading, error } = useApi('/products');

  if (loading) return <Spinner />;
  if (error) return <Error message={error.message} />;

  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

5. Обработка ошибок

Глобальная обработка ошибок через интерсепторы:

// Добавляем в axiosConfig.js
apiClient.interceptors.response.use(
  response => response,
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // Перенаправление на страницу логина
          break;
        case 403:
          // Показать уведомление о недостатке прав
          break;
        case 404:
          // Показать 404 страницу
          break;
        default:
          console.error('Server error:', error.response.data);
      }
    }
    return Promise.reject(error);
  }
);

6. Отмена запросов

import { useEffect } from 'react';
import axios from 'axios';

function SearchResults({ query }) {
  useEffect(() => {
    const source = axios.CancelToken.source();

    const fetchResults = async () => {
      try {
        const response = await apiClient.get('/search', {
          params: { q: query },
          cancelToken: source.token
        });
        // Обработка результатов
      } catch (error) {
        if (!axios.isCancel(error)) {
          // Обработка реальной ошибки
        }
      }
    };

    fetchResults();

    return () => {
      source.cancel('Operation canceled due to new request');
    };
  }, [query]);
}

7. Загрузка файлов

const uploadFile = async file => {
  const formData = new FormData();
  formData.append('file', file);

  try {
    const response = await apiClient.post('/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: progressEvent => {
        const percent = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        );
        console.log(`${percent}% uploaded`);
      }
    });
    console.log('Upload complete:', response.data);
  } catch (error) {
    console.error('Upload error:', error);
  }
};

Лучшие практики

  1. Разделение кода: API-логику выносите в отдельные сервисные модули
  2. Инкапсуляция: Создавайте отдельные методы для разных API-эндпоинтов
  3. Типизация: Используйте TypeScript для типизации ответов API
  4. Мокинг: Для тестов используйте axios-mock-adapter
  5. Безопасность: Всегда санируйте данные перед отправкой

Резюмируем

Axios в React используется через создание настроенного экземпляра, интеграцию с хуками и обработку состояний загрузки/ошибок. Для сложных приложений рекомендуется создавать кастомные хуки и сервисные слои для работы с API. Правильная настройка интерсепторов и отмены запросов существенно улучшает пользовательский опыт.