← Назад к вопросам

Приведи пример кастомных Hook

1.0 Junior🔥 31 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример и разбор кастомного хука в React

Кастомный хук (custom hook) — это функция, использующая стандартные хуки React (useState, useEffect, useContext, etc.) для создания повторно используемой логики с состоянием. Основное правило: имя должно начинаться с use, чтобы React понимал, что это хук, и мог применять свои правила (например, проверку порядка вызовов хуков).

Практический пример: хук useFetch для управления HTTP-запросами

Одна из самых распространенных задач в фронтенд-разработке — загрузка данных из API. Часто приходится управлять состоянием загрузки (loading), данными (data) и ошибками (error). Чтобы избежать дублирования кода в каждом компоненте, мы можем создать хук useFetch.

import { useState, useEffect } from 'react';

/**
 * Кастомный хук для выполнения HTTP-запросов.
 * @param {string} url - URL для запроса.
 * @param {object} options - Опции для fetch (method, headers, body, etc.).
 * @returns {object} Объект с состоянием: { data, loading, error }
 */
function useFetch(url, options = {}) {
  // Состояния для данных, загрузки и ошибки
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Асинхронная функция для выполнения запроса
    const fetchData = async () => {
      try {
        setLoading(true);
        setError(null); // Сбрасываем ошибку перед новым запросом
        
        const response = await fetch(url, options);
        
        // Проверяем статус ответа
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const jsonData = await response.json();
        setData(jsonData);
      } catch (err) {
        setError(err.message || 'An unknown error occurred');
        setData(null); // Сбрасываем данные при ошибке
      } finally {
        setLoading(false);
      }
    };

    fetchData();
    
    // Опционально: добавление зависимости для повторного запроса при изменении url
    // Если url или options изменятся, эффект выполнится снова
  }, [url]); // Добавляем url в зависимости, чтобы запрос повторялся при его изменении

  // Возвращаем объект с состояниями, чтобы компонент мог их использовать
  return { data, loading, error };
}

export default useFetch;

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

Теперь любой компонент может использовать этот хук, чтобы получить данные без повторения логики управления состоянием.

import React from 'react';
import useFetch from './useFetch'; // Импорт кастомного хука

function UserProfile({ userId }) {
  // Используем хук. При изменении userId запрос автоматически повторяется.
  const { data: user, loading, error } = useFetch(`https://api.example.com/users/${userId}`);

  // Рендер компонента на основе состояния
  if (loading) return <div>Loading user profile...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h1>User Profile</h1>
      <p><strong>Name:</strong> {user.name}</p>
      <p><strong>Email:</strong> {user.email}</p>
    </div>
  );
}

export default UserProfile;

Преимущества кастомного хука useFetch

  • Уменьшение дублирования кода: Логика запроса, обработки ошибок и управления состоянием загрузки инкапсулирована в одном месте.
  • Упрощение компонентов: Компоненты становятся более чистыми и читаемыми, фокусируются на рендере, а не на побочных эффектах.
  • Легкость тестирования: Хук можно тестировать отдельно от компонентов.
  • Совместное использование: Любой компонент в приложении может импортировать и использовать useFetch.
  • Стандартизация: Все запросы в приложении будут обрабатываться одинаково, что упрощает поддержку и дебаггинг.

Более сложный пример: хук useLocalStorage

Кастомные хуки могут взаимодействовать не только с API, но и с браузерным API, например, localStorage.

import { useState, useEffect } from 'react';

/**
 * Хук для синхронизации состояния React с localStorage.
 * @param {string} key - Ключ в localStorage.
 * @param {any} initialValue - Начальное значение, если в localStorage ничего нет.
 * @returns {[any, function]} Аналогично useState: [value, setValue]
 */
function useLocalStorage(key, initialValue) {
  // Функция для чтения начального значения из localStorage или использования initialValue
  const readValue = () => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.warn(`Error reading localStorage key "${key}":`, error);
      return initialValue;
    }
  };

  const [storedValue, setStoredValue] = useState(readValue);

  // Функция-обертка для setStoredValue, которая также сохраняет значение в localStorage
  const setValue = (value) => {
    try {
      // Позволяем value быть функцией, как в стандартном useState
      const newValue = value instanceof Function ? value(storedValue) : value;
      setStoredValue(newValue);
      window.localStorage.setItem(key, JSON.stringify(newValue));
    } catch (error) {
      console.warn(`Error setting localStorage key "${key}":`, error);
    }
  };

  // Слушаем изменения этого ключа в localStorage из других окон (табов)
  useEffect(() => {
    const handleStorageChange = (e) => {
      if (e.key === key && e.newValue !== null) {
        setStoredValue(JSON.parse(e.newYearValue));
      }
    };
    window.addEventListener('storage', handleStorageChange);
    return () => window.removeEventListener('storage', handleStorageChange);
  }, [key]);

  return [storedValue, setValue];
}

Использование:

const [theme, setTheme] = useLocalStorage('app-theme', 'light');
// theme автоматически сохраняется в localStorage и восстанавливается при новой загрузке страницы.

Правила создания кастомных хуков

  1. Начинать с use: Это соглашение, которое позволяет React (и линтерам) идентифицировать функцию как хук.
  2. Использовать только стандартные хуки внутри: Кастомный хук может вызывать другие кастомные хуки или стандартные хуки React.
  3. Сохранять чистоту: Хук не должен иметь побочных эффектов на рендер (за исключением тех, что правильно оформлены в useEffect).
  4. Инкапсулировать логику, а не рендер: Хук возвращает данные или функции, но не JSX. Рендер остается ответственностью компонента.

Кастомные хуки — это мощный инструмент для организации логики в React-приложениях, позволяющий создавать переиспользуемые, тестируемые и поддерживаемые части кода, что соответствует принципам чистого кода и эффективной разработки.