Чому setState не змінює стан миттєво?
Коротка відповідь
setState (або setCount, setValue, тощо) не оновлює стан одразу,
тому що React робить оновлення асинхронно і пакетно (batched),
щоб підвищити продуктивність і уникнути зайвих перемальовок.
Що відбувається під капотом
Коли ти викликаєш:
setCount(count + 1);
console.log(count); // старе значення!Ти не бачиш нове значення, тому що React:
- Зберігає твій запит на оновлення (update) у внутрішню чергу.
- Не оновлює одразу, а планує оновлення компонента.
- Виконує всі накопичені зміни одним рендером, трохи пізніше (наприкінці події, ефекту, або при наступному кадрі).
Приклад
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // старе значення
};
useEffect(() => {
console.log("Оновлено:", count); // нове значення
}, [count]);
return <button onClick={handleClick}>{count}</button>;
}Усередині handleClick - console.log виводить старе значення,
але в useEffect (після оновлення) - вже нове.
Чому React робить саме так
1. Оптимізація продуктивності
Якби React оновлював компонент миттєво при кожному setState,
а в тебе, наприклад, 10 викликів поспіль - він би 10 разів перемалював компонент.
Замість цього React групує (batching) всі оновлення:
setCount(c => c + 1);
setCount(c => c + 1);
setCount(c => c + 1);-> все виконається одним рендером, а count стане +3.
2. Асинхронна природа рендерингу (Fiber)
React 18+ використовує конкурентний (concurrent) рендеринг:
- він може призупиняти, об'єднувати і відкладати оновлення;
- він вирішує, коли безпечно оновити UI, щоб не блокувати інтерфейс.
Тому setState - це запит на оновлення,
а не негайна зміна даних.
3. Передбачуваність і чистота коду
React завжди ререндерить компонент з нуля,
беручи новий стан зі своєї внутрішньої черги.
Якби setState змінював значення миттєво,
ти міг би випадково використати "наполовину оновлені" дані.
Підсумок
| Питання | Відповідь |
|---|---|
Чому setState не миттєвий? | Тому що React оновлює стан асинхронно і пакетно |
Що робить React при setState? | Кладе оновлення в чергу і планує ререндер |
| Коли з'явиться нове значення? | При наступному ререндері компонента |
| Де можна побачити нове значення? | У useEffect, в UI, або в callback setState |
Хитрий момент
Якщо тобі потрібно оновити стан на основі попереднього, завжди використовуй функціональну форму:
setCount(prev => prev + 1);Так React гарантує, що ти отримаєш актуальний стан, навіть якщо оновлень декілька і вони виконуються пакетно.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.