Что такое Fetch API и как его использовать в React?react-88

Что такое Fetch API?

Fetch API — это современный нативный браузерный интерфейс для выполнения HTTP-запросов, который пришел на смену устаревшему XMLHttpRequest. Это promise-based API, предоставляющее более простой и мощный способ работы с сетевыми запросами.

Основные преимущества

  1. Встроен в браузер — не требует дополнительных зависимостей
  2. Promise-based — удобная работа с асинхронными операциями
  3. Более чистый синтаксис по сравнению с XMLHttpRequest
  4. Поддержка современных стандартов (CORS, streaming и др.)

Базовый пример использования

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

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

1. Простой GET-запрос с useState и useEffect

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // Пустой массив зависимостей = выполняется один раз при монтировании

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

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

2. POST-запрос с отправкой данных

async function postData(url = '', data = {}) {
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });
  return response.json();
}

// Использование в компоненте:
const handleSubmit = async (formData) => {
  try {
    const result = await postData('/api/submit', formData);
    console.log('Success:', result);
  } catch (error) {
    console.error('Error:', error);
  }
};

Продвинутые техники

1. Работа с заголовками

fetch('https://api.example.com/data', {
  headers: new Headers({
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
  })
});

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

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;

  const fetchData = async () => {
    try {
      const response = await fetch('https://api.example.com/data', {
        signal
      });
      // Обработка данных
    } catch (err) {
      if (err.name === 'AbortError') {
        console.log('Fetch aborted');
      } else {
        // Обработка других ошибок
      }
    }
  };

  fetchData();

  return () => controller.abort(); // Отмена запроса при размонтировании
}, []);

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

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

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
    // Заголовок Content-Type не нужен для FormData!
  });

  return response.json();
};

Сравнение с Axios

  1. Преимущества Fetch API:

    • Не требует дополнительных зависимостей
    • Современный стандарт, поддерживаемый всеми браузерами
    • Более низкоуровневый контроль
  2. Недостатки Fetch API:

    • Нет встроенных интерсепторов
    • Более многословная обработка ошибок
    • Нет автоматической трансформации JSON
    • Нет встроенного прогресса загрузки

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

  1. Создание вспомогательных функций для повторяющихся запросов
  2. Обработка всех возможных ошибок (сети, парсинга, сервера)
  3. Очистка эффектов с помощью AbortController
  4. Разделение логики — выносите запросы в отдельные модули

Пример вспомогательной функции:

async function fetchJson(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
    body: options.body ? JSON.stringify(options.body) : undefined,
  });

  if (!response.ok) {
    const error = new Error(`HTTP error! status: ${response.status}`);
    error.status = response.status;
    throw error;
  }

  return response.json();
}

Интеграция с React Query

import { useQuery } from 'react-query';

function UserList() {
  const { data, isLoading, error } = useQuery('users', () =>
    fetch('/api/users').then(res => res.json())
  );

  // Отрисовка компонента
}

Резюмируем

Fetch API — это мощный нативный инструмент для HTTP-запросов в React-приложениях. Для базовых сценариев он отлично подходит без дополнительных зависимостей. Для сложных случаев можно комбинировать его с библиотеками типа React Query или перейти на Axios. Ключевые моменты — правильная обработка ошибок и состояний загрузки.