Как работает хук useState в React и на что он влияет
Что проверяют
Понимаете ли вы, что состояние это снимок на момент рендера, и знаете ли про пакетирование и функциональное обновление.
Как отвечать
useState возвращает текущее значение и функцию его изменения. Вызов функции не меняет переменную немедленно, а планирует перерисовку. Значение в текущем рендере остаётся прежним, потому что это константа из замыкания этого рендера.
const [count, setCount] = useState(0);
function handle() {
setCount(count + 1);
setCount(count + 1); // увеличит на 1, а не на 2: count в обоих вызовах старый
setCount(c => c + 1); // так на 1 больше от актуального
}Отсюда правило: обновление, зависящее от предыдущего значения, пишут функцией.
Что ещё важно:
- пакетирование: несколько вызовов в одном обработчике дают одну перерисовку. С React 18 это работает везде, включая таймеры и промисы;
- сравнение по
Object.is: если новое значение то же самое, перерисовки не будет. Мутация объекта не меняет ссылку, поэтому и перерисовки не вызовет, отсюда правило создавать новый объект; - ленивая инициализация:
useState(() => heavy())вычислит начальное значение один раз, аuseState(heavy())будет вызывать функцию на каждом рендере; - состояние привязано к позиции хука в дереве, поэтому хуки нельзя вызывать в условиях и циклах;
- сброс состояния при смене
keyкомпонента: это штатный приём, а не побочный эффект.
Где спотыкаются
Читают состояние сразу после установки и удивляются старому значению.
Мутируют массив или объект в состоянии и не получают перерисовку.
Вызывают тяжёлую функцию прямо в аргументе useState.
Держат в состоянии то, что можно вычислить из других значений.