Гид по технологиям

Кастомный React‑хук useFetch — как и зачем

3 min read React Hooks Обновлено 27 Nov 2025
Кастомный React‑хук useFetch — как и зачем
Кастомный React‑хук useFetch — как и зачем

Фокусный стальной крючок на размытом фоне

Зачем выносить логику загрузки в кастомный хук

Кратко: вынос логики загрузки в хук делает код компонентов чище, повышает переиспользуемость и упрощает тестирование. Хук инкапсулирует состояния загрузки, ошибки и данные, а компонент просто их отображает.

Определение терминов (одно предложение):

  • useEffect — хук для побочных эффектов, запускается при изменении зависимостей.
  • useState — хук для локального состояния в компоненте.
  • AbortController — стандартный API для отмены fetch‑запросов.

Принципы хорошего useFetch

  • Обрабатывать сетевые ошибки и ошибки формата ответа.
  • Возвращать явные состояния: data, loading, error.
  • Отменять предыдущий запрос при размонтировании или при смене URL.
  • Не изменять состояние после размонтирования компонента.
  • Подумать о кешировании и повторных попытках в другом слое (например, React Query).

Пример улучшённого хука useFetch

Ниже — реалистичный и безопасный вариант хука с поддержкой отмены, проверки статуса ответа и аккуратной работой со state:

import { useEffect, useState } from "react";

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(Boolean(url));
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!url) {
      setData(null);
      setLoading(false);
      setError(null);
      return;
    }

    const controller = new AbortController();
    const signal = controller.signal;

    const fetchData = async () => {
      setLoading(true);
      setError(null);

      try {
        const res = await fetch(url, { signal });
        if (!res.ok) {
          // Простая унификация ошибок по статусу
          throw new Error(`HTTP error ${res.status}`);
        }
        const json = await res.json();
        // Пример: формат API может отличаться, здесь мы пытаемся безопасно выбрать поле
        const payload = json?.joke ?? json?.data ?? json;
        setData(payload);
      } catch (err) {
        if (err.name === 'AbortError') {
          // Запрос отменён — игнорируем
          return;
        }
        setError(err.message || 'Unknown error');
      } finally {
        setLoading(false);
      }
    };

    fetchData();

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

  return { data, loading, error };
};

export default useFetch;

Important: этот хук рассчитан на общие случаи. Если ваш API возвращает потоковые ответы, multipart или двоичные данные, потребуется другой подход.

Пример использования хука в компоненте

import React from 'react';
import useFetch from './useFetch';

const Jokes = () => {
  const url = 'https://sv443.net/jokeapi/v2/joke/Programming?type=single';
  const { data, loading, error } = useFetch(url);

  if (loading) return 
Загрузка...
; return (
{error &&
Ошибка: {error}
} {data &&
{data}
}
); }; export default Jokes;

Советы по использованию:

  • Не забывайте кешировать или мемоизировать URL, если он строится динамически.
  • Для повторных попыток и продвинутых стратегий используйте библиотеки вроде React Query.

Когда этот подход не подходит

  • Если нужен встроенный кеш, дедупликация запросов и повторные попытки — лучше React Query/SWR.
  • Для крупных потоковых загрузок (видео, аудио) fetch + JSON не подойдёт.
  • Когда нужен персистентный TSO (transactional state) — тогда нужны серверные решения.

Альтернативные подходы

  • axios: проще в синтаксисе, автоматически обрабатывает JSON и статусы; поддерживает отмену через CancelToken/AbortController.
  • SWR / React Query: добавляют кеширование, фоновое обновление и утилиты для retry и stale‑while‑revalidate.
  • GraphQL клиенты (Apollo, Urql) — если API GraphQL.

Ментальные модели и эвристики

  • Хук = функция, инкапсулирующая состояние + побочные эффекты. Держите хук маленьким и однозадачным.
  • Передавайте только параметры (URL, опции), не абстрагируйте бизнес‑логику внутрь хука.
  • Любая асинхронная операция должна предусматривать отмену и обработку ошибок.

Чеклист для разработчика

  • URL стабилен и мемоизирован, если вычисляется.
  • Обработаны HTTP‑ошибки (res.ok).
  • Использован AbortController для отмены.
  • Состояние loading переключается корректно (true → false).
  • Не устанавливается state после размонтирования компонента.
  • Ошибки приводят к понятным сообщениям для пользователя.

Критерии приёмки

  • Хук возвращает { data, loading, error } для всех тестовых URL.
  • При размонтировании не происходит утечек памяти и не выбрасываются ошибки о setState на размонтированном компоненте.
  • Поведение при недоступном API: loading → false, error содержит текст ошибки.
  • При успешном ответе data содержит ожидаемую полезную нагрузку.

Тест‑кейсы (минимум)

  1. Успешный ответ 200 с JSON → loading: false, error: null, data: корректно распарсено.
  2. HTTP 4xx/5xx → loading: false, error содержит статус.
  3. Отмена запроса (размонтирование) → нет ошибок, state не меняется после размонтирования.
  4. Пустой или некорректный URL → hook корректно возвращает loading: false и data: null.

Глоссарий (1‑строчно)

  • fetch — встроенный браузерный API для HTTP‑запросов.
  • AbortController — механизм отмены fetch‑запроса.
  • useEffect/useState — React‑хуки для побочных эффектов и локального состояния.

Короткая заметка для команды (социальный анонс)

Добавили переиспользуемый React‑хук useFetch: отмена запросов, обработка ошибок и пример использования. Если нужно кеширование и retry — рассмотрите React Query.

КОНЕЦ. Надёжный хук для большинства простых сценариев загрузки данных и удобная отправная точка для перехода на более продвинутые библиотеки.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Unity Lights: циферблат Apple Watch для Black History Month
Apple Watch

Unity Lights: циферблат Apple Watch для Black History Month

Обновление видеодрайвера для Rainbow Six Siege
Windows

Обновление видеодрайвера для Rainbow Six Siege

Ограничение частоты запросов в ASP.NET Core
Backend

Ограничение частоты запросов в ASP.NET Core

Исправление лагов Android: TRIM и LagFix
Mobile

Исправление лагов Android: TRIM и LagFix

Семафоры в Bash: что это и как реализовать
Bash

Семафоры в Bash: что это и как реализовать

Что делать при перегреве PS5
Гайды

Что делать при перегреве PS5