PassFront
  1. PassFront
  2. База знаний
  3. Хуки

Разбери, может ли useState принять callback: в каких случаях и от чего это зависит.

Хуки

useState «принимает callback» в двух разных смыслах — и оба легальны, но работают по-разному: ленивый инициализатор при создании и функциональное обновление в сеттере.

Случай 1: функция как начальное значение (lazy initializer)

const [data, setData] = useState(() => JSON.parse(localStorage.getItem('draft')));

Если передать в useState функцию, React вызовет её один раз при монтировании и возьмёт результат как начальное значение. Когда это нужно: дорогая инициализация (парсинг, чтение localStorage, построение структуры) — без ленивой формы выражение вычислялось бы на каждом рендере (результат бы игнорировался, но CPU тратился).

useState(compute());     // compute() выполняется КАЖДЫЙ рендер
useState(() => compute()); // compute() выполняется один раз

Случай 2: функция в сеттере (functional update)

setCount((prev) => prev + 1);

Сеттер с функцией применяет её к актуальному предыдущему значению из очереди обновлений. Когда это нужно:

  • несколько обновлений подряд: два setCount((c) => c + 1) дадут +2, а два setCount(count + 1) — только +1 (оба замкнули старый count);
  • обновление из колбэков с устаревшим замыканием (таймеры, подписки с []).

Чего useState НЕ умеет

Хранить функцию «как есть» напрямую нельзя — она будет истолкована как инициализатор/апдейтер. Функцию-значение оборачивают:

const [handler, setHandler] = useState(() => defaultFn); // хранение функции
setHandler(() => newFn);

И: колбэка «после обновления» (как второй аргумент this.setState в классах) у useState нет — реагировать на изменение нужно через useEffect.

Коротко для собеседования

Да, в двух формах: useState(() => init) — ленивый инициализатор, вызывается один раз (для дорогой инициализации); setX((prev) => next) — функциональное обновление от актуального значения (для серий обновлений и устаревших замыканий). Хранить функцию — только через обёртку; колбэка «после setState» нет — это делает useEffect.

Другие вопросы раздела