Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
React хуки — практический опыт использования
За годы работы с React я использовал практически весь арсенал хуков — как встроенных, так и кастомных. Расскажу подробно о каждом из них с реальными примерами применения.
Базовые хуки
useState
Самый используемый хук. Применяю для управления локальным состоянием компонента.
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState<FormData>({ name: "", email: "" });
Важный нюанс: при обновлении объектов/массивов нужно создавать новую ссылку — React сравнивает по reference:
setFormData(prev => ({ ...prev, name: "John" })); // правильно
useEffect
Для побочных эффектов: подписки, fetch-запросы, работа с DOM, таймеры.
useEffect(() => {
const controller = new AbortController();
fetchData(controller.signal).then(setData);
return () => controller.abort(); // cleanup
}, [userId]); // зависимость
Одна из самых частых ошибок — пустой массив зависимостей при использовании переменных из замыкания. Всегда следую правилу exhaustive-deps.
useContext
Использую для передачи данных через дерево без prop drilling — тема, локализация, данные пользователя:
const { user, logout } = useContext(AuthContext);
Хуки оптимизации
useMemo
Мемоизирую дорогостоящие вычисления:
const filteredItems = useMemo(() =>
items.filter(item => item.category === selectedCategory),
[items, selectedCategory]
);
Важно: не использую useMemo везде подряд — только когда вычисление реально дорогое или когда нужна стабильная ссылка на объект для передачи в дочерний компонент.
useCallback
Стабилизирую функции-коллбэки, которые передаются в дочерние компоненты или в зависимости других хуков:
const handleSubmit = useCallback(async (data: FormData) => {
await api.submitForm(data);
onSuccess();
}, [onSuccess]);
useRef
Использую для двух разных целей:
- Доступ к DOM-элементу:
const inputRef = useRef<HTMLInputElement>(null);
// inputRef.current?.focus();
- Хранение мутабельного значения без ререндера:
const timerRef = useRef<NodeJS.Timeout | null>(null);
const previousValueRef = useRef(value);
Хуки React 18
useTransition
Для пометки некритичных обновлений — например, фильтрация большого списка при вводе:
const [isPending, startTransition] = useTransition();
const handleSearch = (query: string) => {
setInputValue(query); // срочное обновление инпута
startTransition(() => {
setFilteredItems(filterHeavyList(query)); // отложенное
});
};
useDeferredValue
Альтернатива useTransition когда не контролируешь источник обновления:
const deferredQuery = useDeferredValue(searchQuery);
const results = useMemo(() => search(deferredQuery), [deferredQuery]);
useId
Для генерации уникальных id доступности (accessibility):
const id = useId();
// <label htmlFor={id}> + <input id={id}>
useReducer
Применяю когда логика состояния сложная — несколько связанных значений, сложные переходы:
type Action =
| { type: "FETCH_START" }
| { type: "FETCH_SUCCESS"; payload: Item[] }
| { type: "FETCH_ERROR"; payload: string };
const [state, dispatch] = useReducer(reducer, initialState);
Кастомные хуки
Активно выношу повторяющуюся логику в кастомные хуки:
// useLocalStorage
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
const setStoredValue = useCallback((newValue: T) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
}, [key]);
return [value, setStoredValue] as const;
}
// useDebounce
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
useLayoutEffect
Использую редко — только когда нужно синхронно прочитать и модифицировать DOM до отрисовки:
useLayoutEffect(() => {
// Измерить размер элемента перед тем, как браузер нарисует UI
const { height } = ref.current.getBoundingClientRect();
setHeight(height);
}, []);
Итог
Хуки кардинально изменили подход к разработке на React — логика теперь компонуется через функции, а не через класс-компоненты с их запутанными жизненными циклами. Главное правило, которому следую: хук должен делать одно дело и хорошо. Кастомные хуки — мощнейший инструмент для DRY и переиспользования логики между компонентами.