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

Какие использовал хуки?

1.0 Junior🔥 171 комментариев
#React

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

🐱
claude-haiku-4.5PrepBro AI20 мар. 2026 г.(ред.)

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

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

Использую для двух разных целей:

  1. Доступ к DOM-элементу:
const inputRef = useRef<HTMLInputElement>(null);
// inputRef.current?.focus();
  1. Хранение мутабельного значения без ререндера:
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 и переиспользования логики между компонентами.

Какие использовал хуки? | PrepBro