В чем разница useReducer и useState в React
Что проверяют
Понимаете ли вы, когда набор связанных полей выгоднее свести в одно состояние с явными переходами.
Как отвечать
Внутри это один и тот же механизм, useState можно выразить через useReducer. Разница в том, где живёт логика перехода: в компоненте или в отдельной чистой функции.
useState подходит, когда значение простое и независимое: флаг открытия, текст поля, выбранная вкладка.
useReducer берут, когда:
- несколько полей меняются вместе. Загрузка данных это
loading,dataиerror, и обновлять их тремя вызовами значит рано или поздно получить состояние «идёт загрузка и уже есть ошибка». Редьюсер описывает переход целиком и делает невозможные комбинации непредставимыми; - следующее состояние сложно зависит от предыдущего: корзина, редактор, многошаговая форма, отмена действия;
- действий много и они с именами:
{ type: "submit_failed" }читается лучше, чем цепочка вызовов установки значений, и в отладке видно, что произошло; - логику хочется протестировать: редьюсер это чистая функция, ей не нужен ни React, ни рендеринг;
- функцию обновления надо передать вниз:
dispatchстабилен между рендерами, поэтому не ломает мемоизацию дочерних компонентов, в отличие от набора колбэков, которые приходится оборачивать вuseCallback.
Пример перехода к редьюсеру обычно выглядит так: было четыре вызова useState, между ними появились противоречивые сочетания, и они свелись к одному состоянию с полем-статусом.
Правило по выбору: начинайте с useState, а переходите к useReducer, когда ловите себя на том, что обновляете несколько значений подряд и боитесь забыть одно из них.
Где спотыкаются
Считают useReducer заменой Redux или чем-то только для больших приложений.
Держат связанные поля в отдельных состояниях и получают противоречивые комбинации.
Пишут редьюсер с побочными эффектами внутри: запросами, работой с хранилищем.
Мутируют состояние в редьюсере вместо возврата нового объекта.