Як оновити стан на основі попереднього значення?
1. Проблема при звичайному оновленні
Уяви компонент:
function Counter() {
const [count, setCount] = useState(0);
const incrementTwice = () => {
setCount(count + 1);
setCount(count + 1);
};
return <button onClick={incrementTwice}>{count}</button>;
}Ти очікуєш, що при кліку count збільшиться на 2...
але насправді - лише на 1!
Чому так відбувається
setCount не оновлює count одразу (він асинхронний).
Обидва рядки використовують старе значення count (наприклад, 0).
React просто ставить у чергу два однакових оновлення:
"зроби count = 1".
Результат - одне оновлення, значення 1.
2. Правильний спосіб - функціональне оновлення
React дозволяє передати в setState функцію,
яка отримує попереднє значення стану:
setCount(prevCount => prevCount + 1);Тепер React гарантує, що ти працюєш з актуальним станом, навіть якщо було кілька оновлень поспіль.
Приклад з incrementTwice
function Counter() {
const [count, setCount] = useState(0);
const incrementTwice = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
};
return <button onClick={incrementTwice}>{count}</button>;
}Тепер при кліку count збільшиться на 2
тому що кожна функція отримує останнє оновлене значення.
3. Аналогічно працює з об'єктами і масивами
Наприклад:
const [user, setUser] = useState({ name: "Tim", points: 0 });
function addPoint() {
setUser(prev => ({ ...prev, points: prev.points + 1 }));
}Тут prev - це попередній стан user,
і ти створюєш новий об'єкт на його основі.
4. Приклад з логом (для наочності)
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prev => {
console.log("Попереднє значення:", prev);
return prev + 1;
});
};
return <button onClick={handleClick}>{count}</button>;
}При кожному кліку ти побачиш у консолі актуальне "попереднє" значення, яке React гарантує навіть при асинхронних апдейтах.
5. Підсумок
| Що ти хочеш зробити | Як писати |
|---|---|
| Встановити фіксоване значення | setCount(10) |
| Збільшити на 1 | setCount(prev => prev + 1) |
| Додати елемент у масив | setItems(prev => [...prev, newItem]) |
| Змінити поле об'єкта | setUser(prev => ({ ...prev, name: "Alex" })) |
Висновок
setState(value) - просто встановлює новий стан
setState(prev => newValue) - оновлює на основі попереднього значення
Це безпечний спосіб при:
- кількох викликах поспіль,
- асинхронних оновленнях,
- залежних обчисленнях (наприклад, лічильники, масиви, об'єкти)
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.