Хуки в React
Что такое “хуки” (hooks) в React и для чего они используются?
Хуки (
Hooks
) — это функции, которые позволяют использовать состояние и
другие возможности React в функциональных компонентах.
Основные хуки:
-
useState:-
Управляет состоянием в функциональных компонентах.
-
Пример:
const [count, setCount] = useState(0);
-
-
useEffect:-
Выполняет побочные эффекты, такие как загрузка данных, в функциональных компонентах.
-
Пример:
useEffect(() => { // Выполнение побочного эффекта }, []);
-
-
useContext:-
Использует контекст для доступа к глобальным данным.
-
Пример:
const value = useContext(MyContext);
-
-
useReducer:-
Управляет сложным состоянием с помощью редюсеров.
-
Пример:
const [state, dispatch] = useReducer(reducer, initialState);
-
-
useMemo:-
Мемоизирует вычисленные значения для оптимизации производительности.
-
Пример:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
-
-
useCallback:-
Мемоизирует функции для оптимизации производительности.
-
Пример:
const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
-
Хуки в React позволяют функциональным компонентам использовать состояние и другие возможности, упрощая управление состоянием, побочными эффектами и контекстом в приложениях.
Ссылки для изучения
Как создать собственный хук в React?
Собственный хук (custom hook) позволяет абстрагировать и повторно использовать логику состояния и эффектов в функциональных компонентах.
Шаги:
-
Создайте функцию, название которой начинается с
use:- Собственные хуки должны следовать соглашению об именовании, начинаясь с
use.
- Собственные хуки должны следовать соглашению об именовании, начинаясь с
-
Используйте внутри функции стандартные хуки React (
useState,useEffect, и т.д.):- Собственный хук может использовать любые стандартные хуки React.
-
Возвращайте необходимые значения или функции из собственного хука:
- Возвращайте данные и функции, которые должны быть доступны в компоненте.
Пример:
import { useState, useEffect } from "react";
// Создание собственного хука для получения данных
const useFetchData = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
} catch (err) {
setError(err);
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
};
export default useFetchData;
Использование собственного хука в компоненте:
import React from "react";
import useFetchData from "./useFetchData";
const MyComponent = () => {
const { data, loading, error } = useFetchData("https://api.example.com/data");
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{JSON.stringify(data)}</div>;
};
export default MyComponent;
Создание собственного хука в React позволяет абстрагировать повторяющуюся логику и легко использовать её в различных компонентах, улучшая структуру и повторное использование кода.
Ссылки для изучения
Какие особенности имеют хуки useEffect и useLayoutEffect?
useEffect и useLayoutEffect — это хуки в React,
которые используются для выполнения побочных эффектов в функциональных
компонентах, но они выполняются в разное время.
useEffect:
-
Выполнение после рендеринга:
-
Выполняется после commit. Обычно браузер успевает нарисовать экран до эффекта, но эффект, вызванный взаимодействием пользователя, может выполниться до отрисовки.
-
Подходит для операций, не влияющих на отображение, таких как данные, запросы и подписки.
-
-
Использование:
useEffect(() => { // Побочные эффекты, например, загрузка данных return () => { // Очистка при размонтировании }; }, [dependencies]); // Зависимости
useLayoutEffect:
-
Выполнение перед отрисовкой браузером:
-
Выполняется после обновления DOM, но до отрисовки экрана браузером. Эффект и обновления состояния внутри него блокируют эту отрисовку.
-
Подходит для операций, влияющих на макет и измерения, таких как анимации и манипуляции с DOM.
-
-
Использование:
useLayoutEffect(() => { // Побочные эффекты, например, измерения DOM return () => { // Очистка при размонтировании }; }, [dependencies]); // Зависимости
-
useEffect: Выполняется после рендеринга, подходит для асинхронных операций и побочных эффектов, не влияющих на макет. -
useLayoutEffect: выполняется после commit, до отрисовки браузером; подходит для измерения DOM перед показом результата.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- СОБЕСЕДОВАНИЕ Middle FRONTEND разработчика | JavaScript REACT TYPESCRIPT · 1:04:50–1:05:52Техническое собеседование · Объяснение интервьюера
Интервьюер объясняет useLayoutEffect на измерении DOM и изменении размеров до показа кадра: как избежать мерцания и почему тяжёлые вычисления здесь задерживают отрисовку.
Зачем useEffect возвращает cleanup-функцию?
Cleanup отменяет или симметрично завершает то, что setup эффекта начал. React вызывает его перед повторным запуском эффекта с изменившимися зависимостями и при размонтировании. Поэтому подписку снимают тем же handler, таймер очищают, запрос отменяют, а внешний widget уничтожают. В development Strict Mode React дополнительно выполняет цикл setup-cleanup-setup, чтобы обнаружить несимметричный код; на production-поведение этого как гарантии не полагаются. Cleanup не должен без причины обновлять React state. Хороший тест: после cleanup внешний мир выглядит так, будто этот запуск эффекта не происходил.
Ссылки для изучения
Какие ресурсы нужно освобождать при размонтировании React-компонента?
Освобождают таймеры и animation frame, снимают DOM и библиотечные подписки, закрывают WebSocket или EventSource, отменяют поддерживаемые запросы. IntersectionObserver, ResizeObserver и MutationObserver отключают; созданный chart, map, editor или media instance уничтожают его API. Для shared connection cleanup уменьшает reference count, а не обязательно закрывает ресурс для всех. Очистка должна быть симметрична конкретному setup и безопасна при повторном вызове. Если библиотека сама управляет только DOM-узлом, удаляемым React, отдельный cleanup может не понадобиться, но это подтверждают её контрактом.
Ссылки для изучения
Как выбирать зависимости useEffect и избегать stale closure?
В зависимости включают каждое reactive value, прочитанное внутри эффекта: props, state и функции или объекты из тела компонента. Это не ручной выбор частоты запуска, а описание данных эффекта. Пропуск создаёт stale closure, где callback видит старые значения. Если объект меняется на каждом render, его создают внутри эффекта, мемоизируют по настоящим зависимостям либо выносят стабильную часть наружу. Для update из предыдущего state используют функциональный setter. Правило exhaustive-deps лучше исправлять изменением структуры; отключение допустимо только при доказанном инварианте, который код делает очевидным.
Ссылки для изучения
Когда useEffect запускается без массива зависимостей?
Если второй аргумент не передан, effect запускается после каждого commit компонента. Перед новым запуском React сначала выполняет cleanup предыдущего. Если effect безусловно меняет state, а это изменение вызывает новый render, легко получить цикл; React прекратит его ошибкой только после множества обновлений. Это не значит, что всегда нужно добавить пустой массив. Нужно описать реальные reactive dependencies или убрать effect, если значение можно вычислить во время render. В development Strict Mode возможен дополнительный setup-cleanup цикл, поэтому эффект обязан быть симметричным.
Ссылки для изучения
Какие значения стоит хранить в useRef помимо DOM-узла?
useRef хранит изменяемое значение между рендерами без запуска нового render. В нём удобно держать ID таймера, предыдущие данные для сравнения, AbortController, экземпляр стороннего API или последнее значение, которое читает внешний callback. Ref подходит только тому, что не участвует в текущем JSX. Если изменение должно сразу отобразиться, нужен state. Не стоит читать или писать ref.current во время render, кроме предсказуемой ленивой инициализации: это нарушает чистоту компонента. Cleanup освобождает внешний ресурс, на который указывает ref.
Ссылки для изучения







