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

Создание кастомного хука useFetch в React

4 min read Веб-разработка Обновлено 09 Jan 2026
useFetch: кастомный хук для React
useFetch: кастомный хук для React

Крупный план нержавеющего стального крюка на нейтральном фоне

Зачем выносить логику получения данных в хук

Современные приложения часто запрашивают данные из внешних API. Если логика запроса и обработки ответов разбросана по компонентам, появляются дублирование, сложность тестирования и риск ошибок (например, утечек при размонтировании). Кастомный хук решает эти проблемы: он инкапсулирует состояния data/loading/error и поведение (fetch, отмена, повторная попытка).

Кратко:

  • Паттерн: вынести fetch в хук и вернуть { data, loading, error }.
  • Польза: повторное использование, единая обработка ошибок, проще тестировать.

Простой пример: минимальный useFetch

Ниже — минимальная реализация, похожая на исходный пример. Она демонстрирует идею, но её можно улучшить.

import { useEffect, useState } from "react";

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

  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setError(data.error);
        setData(data.joke);
        setLoading(false);
      });
  }, [url]);

  return { data, loading, error };
};

export default useFetch;

Важно: в этом минимальном примере нет обработки сетевых ошибок, нет проверки response.ok и он может вызвать попытку обновления состояния после размонтирования компонента.

Усовершенствованный useFetch: обработка ошибок и отмена запросов

Ниже — более надёжная версия хука с AbortController, обработкой ошибок, повторным использованием response.json(), и корректной установкой состояния даже при ошибках.

import { useEffect, useState } from "react";

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

  useEffect(() => {
    if (!url) return;

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

    const fetchData = async () => {
      setLoading(true);
      setError(null);
      try {
        const res = await fetch(url, { ...options, signal });
        if (!res.ok) {
          const text = await res.text();
          throw new Error(`HTTP ${res.status}: ${text}`);
        }
        const json = await res.json();
        setData(json);
      } catch (err) {
        if (err.name === 'AbortError') return; // отмена запроса при размонтировании
        setError(err.message || 'Ошибка при загрузке данных');
      } finally {
        setLoading(false);
      }
    };

    fetchData();

    return () => controller.abort();
  }, [url]);

  return { data, loading, error };
};

export default useFetch;

Пояснения:

  • AbortController предотвращает попытки обновления state после размонтирования компонента.
  • Проверка res.ok и чтение тела ответа помогают диагностировать ошибки сервера.
  • options позволяет подставлять заголовки (например для токена авторизации).

Важно: не храните в коде секреты (API‑ключи) в открытом виде. Для приватных ключей используйте серверный прокси или защищённые переменные окружения.

Пример использования в компоненте Jokes (локализация строк)

Современный импорт выглядит так:

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.joke || JSON.stringify(data)}
}
); }; export default Jokes;

Совет: используйте role=”alert” для ошибок — это улучшает доступность (a11y).

Когда такой хук не подходит (контрпримеры)

  • Большие приложения с множеством взаимодействующих запросов: лучше использовать React Query или SWR (кеширование, повторные попытки, фоновые обновления).
  • Сложные сценарии синхронизации данных между компонентами и сервером — сторонние библиотеки дадут больше фич.
  • Важно: для WebSocket или стриминга данных этот паттерн не применим напрямую.

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

  • React Query (TanStack Query): готовые решения для кеширования, повторных попыток, фоновой синхронизации.
  • SWR: лаконичный подход с оптимистичным обновлением и повторным валидированием.
  • Axios + кастомные абстракции: если нужна расширенная конфигурация запросов.

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

  • Хук корректно возвращает loading=true до получения ответа.
  • При успешном ответе loading=false и data содержит ответ.
  • При сетевой/серверной ошибке error содержит текст ошибки.
  • При размонтировании компонента запрос отменяется (AbortController).
  • Тесты покрывают успешный ответ, ошибку и отмену.

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

  • Заголовки авторизации не содержат секретов в клиентском коде.
  • Обработаны HTTP‑ошибки (res.ok).
  • Присутствует логика отмены запроса.
  • Ошибки показываются через role=”alert”.
  • Локализация сообщений (например «Загрузка…») настроена при необходимости.

Короткая методология внедрения

  1. Выделите общую логику fetch в useFetch.
  2. Добавьте AbortController и обработку res.ok.
  3. Протестируйте: mock fetch, проверьте отмену и обработку 4xx/5xx.
  4. При необходимости замените на React Query/SWR для продвинутых сценариев.

Безопасность и приватность

  • Не отправляйте персональные данные без HTTPS и без согласия пользователя.
  • Для EU/GDPR: документируйте, какие данные отправляются и где они хранятся на сервере.
  • Для авторизации используйте короткоживущие токены и механизм обновления на сервере.

Тестовые случаи / Acceptance

  • Успешный ответ: mock fetch возвращает JSON → data заполнено, loading=false, error=null.
  • Ошибка сервера: mock fetch с кодом 500 → error содержит сообщение.
  • Отмена: компонент размонтируется до завершения запроса → состояние не обновляется.

Глоссарий в одну строку

  • Hook: функция React, использующая хуки состояния/эффекты для общей логики.
  • useEffect: хук для побочных эффектов, запускается при монтировании/обновлении.
  • AbortController: API для отмены fetch‑запросов.

Резюме

Кастомный хук useFetch — простой и полезный способ централизовать логику получения данных в React. Улучшайте хук постепенно: начните с базовой реализации, добавьте обработку ошибок и отмену запросов, и затем решайте, не пора ли перейти на специализированную библиотеку (React Query или SWR) в зависимости от масштаба приложения.

Полезное: если вам нужно шаблонное поведение (кеш, фоновое обновление, объединение запросов), рассмотрите сторонние решения — они экономят время и снижают вероятность ошибок в крупном проекте.

Спасибо за внимание.

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

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

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство