Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чому setState не змінює стан миттєво?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`setState`** (або `setCount`, `setValue` тощо) не оновлює стан одразу, тому що React робить оновлення **асинхронно і пакетно (batched)**, щоб підвищити продуктивність і уникнути зайвих перемальовок. **Ключове:** нове значення з'являється лише при наступному рендері компонента - у `useEffect`, в UI або у функціональній формі `setState`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь `setState` (або `setCount`, `setValue`, тощо) **не оновлює стан одразу**, тому що React робить оновлення **асинхронно і пакетно (batched)**, щоб підвищити **продуктивність** і **уникнути зайвих перемальовок**. --- ## Що відбувається під капотом Коли ти викликаєш: ```javascript setCount(count + 1); console.log(count); // старе значення! ``` Ти не бачиш нове значення, тому що React: 1. Зберігає твій **запит на оновлення** (update) у внутрішню чергу. 2. Не оновлює одразу, а **планує оновлення** компонента. 3. Виконує всі накопичені зміни **одним рендером**, трохи пізніше (наприкінці події, ефекту, або при наступному кадрі). --- ## Приклад ```javascript 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)** всі оновлення: ```javascript 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` | --- ## Хитрий момент Якщо тобі потрібно оновити стан **на основі попереднього**, завжди використовуй **функціональну форму**: ```javascript setCount(prev => prev + 1); ``` Так React гарантує, що ти отримаєш **актуальний** стан, навіть якщо оновлень декілька і вони виконуються пакетно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.