Гайды

React: компоненты, состояние и хуки

Функциональные компоненты, useState и useEffect, мемоизация, ключи списков, Suspense и чек-лист a11y.

~10 мин чтения

React: компоненты, состояние и хуки

React строит UI из компонентов (функций с хуками). Состояние локально — useState/useReducer, глобально — Context, Zustand, Redux Toolkit, TanStack Query для серверного состояния. Типизация — TypeScript: строгая типизация; SSR — Next.js: SSR и SSG.


1. Функциональный компонент

tsx
type Props = { title: string };

export function Card({ title }: Props) {
  return <article>{title}</article>;
}

2. Состояние и эффекты

tsx
const [n, setN] = useState(0);

useEffect(() => {
  const id = setInterval(() => setN((x) => x + 1), 1000);
  return () => clearInterval(id);
}, []);

Зависимости [] — строго по правилам React; избегайте «немых» эффектов.


3. Мемоизация

useMemo, useCallback, React.memo — только при измеренной проблеме; иначе шум.


4. Списки и ключи

key должен быть стабильным в рамках списка (id сущности), не индекс массива при перестановках.


5. Suspense и границы ошибок

<Suspense> для lazy и data fetching (React 18+ / фреймворки). Error boundaries — классы или библиотеки для отлова рендера.

useSyncExternalStore — правильная подписка на внешнее хранилище (Redux, Zustand vanilla, browser API), чтобы избежать рассинхрона при concurrent rendering; предпочтительнее ручного useEffect + subscribe для сторонних сторов.


6. Стабильные ссылки и useRef

useRef хранит мутабельное значение между рендерами без лишних перерисовок (DOM-нода, таймер id, последнее значение props). Не используйте ref как замену state для UI, который должен реагировать на изменения.


7. Concurrent features

useTransition и useDeferredValue смягчают блокировки UI при тяжёлых обновлениях. startTransition помечает обновления как несрочные; комбинируйте с профилировщиком React.


8. Чек-лист

  • eslint-plugin-react-hooks в CI.
  • Разделение server state (query) и UI state.
  • Доступность (aria, фокус) на интерактивных элементах.
  • useId для связки label/input в SSR без коллизий.
  • Избегать inline object/array в пропсах без мемоизации там, где дочерний список дорогой.

Дальше: Vue.js