setCount(count + 1) не змінює змінну count - він планує новий рендер, у якому useState поверне нове значення. У поточному виконанні функції count лишається тим, яким був на початку рендеру. Стан - це «знімок» для конкретного рендеру.
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
setCount(count + 1);
console.log(count); // 0 - ще старий знімок
}
// після кліку count стане 1, а не 2
}
Обидва виклики порахували 0 + 1.
Функціональне оновлення - передати функцію, яка отримає актуальне значення з черги оновлень:
setCount((c) => c + 1);
setCount((c) => c + 1); // тепер 2
Коли потрібне: коли нове значення залежить від попереднього і оновлень може бути кілька поспіль, а також в асинхронному коді й таймерах, де count у замиканні може бути застарілим.
Ще правила стану:
- Не змінювати стан на місці:
items.push(x); setItems(items)- React порівнює посилання, бачить той самий масив і може не перерендерити. Правильно:setItems([...items, x]). - React групує оновлення (batching): кілька
setStateв одному обробнику дають один рендер.