Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що відбувається при оновленні компонента?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Оновлення (update)** - це стадія життєвого циклу, при якій React повторно викликає компонент, щоб оновити його віртуальне представлення (Virtual DOM) і синхронізувати зміни з реальним DOM. **Ключове:** React порівнює нове віртуальне дерево з попереднім (diffing) і застосовує до реального DOM тільки необхідні зміни, без повної перемальовки сторінки.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке "оновлення" компонента > **Оновлення (update)** - це стадія життєвого циклу, > при якій React повторно викликає компонент, > щоб оновити його **віртуальне представлення (Virtual DOM)** і **синхронізувати зміни з реальним DOM**. --- ## Що запускає оновлення Компонент перемальовується, коли: | Причина | Приклад | |---|---| | Змінився стан (`state`) | `setCount(count + 1)` | | Прийшли нові пропси (`props`) | Батько передав нові дані | | Батьківський компонент сам перерендерився | Навіть якщо пропси не змінилися | | Контекст (`useContext`) оновився | Змінилося значення провайдера | --- ## Етапи оновлення покроково ### 1. Зміна даних React отримує сигнал про те, що дані змінилися: ```javascript setCount(count + 1); ``` Це **не викликає оновлення одразу**. React поміщає оновлення в чергу (batch) і вирішує, коли перерендерити компонент (особливо в React 18 із concurrent rendering). --- ### 2. Повторний виклик функції-компонента React **повторно викликає компонент** (як звичайну функцію), щоб обчислити, який JSX він тепер повинен відрендерити. ```javascript function Counter() { console.log("Рендер"); const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>Лічильник: {count}</button>; } ``` Кожен виклик компонента = новий "рендер". --- ### 3. Порівняння Virtual DOM (diffing) React порівнює **нове віртуальне дерево** (результат нового JSX) з **попереднім деревом**. - Якщо елементи відрізняються -> React змінює тільки ті частини DOM, що змінилися. - Якщо вони однакові -> DOM не чіпається. Це робить оновлення **швидкими і точковими**, без повної перемальовки сторінки. --- ### 4. Оновлення реального DOM React застосовує тільки необхідні зміни до браузерного DOM. Наприклад: якщо змінився тільки текст у кнопці - React замінить **тільки текст**, а не перестворить усю кнопку. --- ### 5. Виконання ефектів (`useEffect`, `useLayoutEffect`) Після того як DOM оновлений, React викликає ефекти, у яких **змінилися залежності**. ```javascript useEffect(() => { console.log("Оновлення: count змінився"); }, [count]); ``` Якщо `count` змінився, ефект виконається знову. Перед цим React викличе **cleanup-функцію** з попереднього ефекту. --- ## Приклад: повний цикл оновлення ```javascript function Example() { const [count, setCount] = useState(0); useEffect(() => { console.log("Монтування"); return () => console.log("Демонтування"); }, []); useEffect(() => { console.log("Оновлення: count =", count); return () => console.log("Очищення перед наступним ефектом"); }, [count]); return ( <button onClick={() => setCount(c => c + 1)}> Лічильник: {count} </button> ); } ``` Що станеться: ```javascript Монтування Оновлення: count = 0 ← перший запуск ефекту (натиснули кнопку) Очищення перед наступним ефектом Оновлення: count = 1 (натиснули кнопку) Очищення перед наступним ефектом Оновлення: count = 2 ``` --- ## Різниця між монтуванням і оновленням | Поведінка | Монтування | Оновлення | |---|---|---| | Чи викликається компонент | Так, вперше | Так, повторно | | Чи створюється DOM | Повністю | Тільки зміни | | `useEffect(() => {...}, [])` | Спрацьовує | Не спрацьовує | | `useEffect(() => {...}, [deps])` | Спрацьовує після монтування | При зміні залежностей | | `cleanup` у `useEffect` | Немає | Перед новим викликом ефекту | --- ## Що зазвичай роблять при оновленні | Завдання | Приклад | |---|---| | Реагувати на зміну даних | `useEffect(() => {...}, [value])` | | Синхронізувати DOM з новим станом | Застосовувати анімації, прокрутку | | Оновлювати підписки | Спершу відписатися, потім підписатися знову | | Перераховувати похідні значення | `useMemo` | | Оптимізувати перерендери | `React.memo`, `useCallback` | --- ## Аналоги в класових компонентах | Етап | Класовий метод | Функціональний аналог | |---|---|---| | Після оновлення | `componentDidUpdate(prevProps, prevState)` | `useEffect(() => {...}, [deps])` | | Перед оновленням (рідко використовується) | `shouldComponentUpdate()` | `React.memo` / `useMemo` / `useCallback` | --- ## Важливо пам'ятати | Особливість | Пояснення | |---|---| | Функція-компонент викликається **заново при кожному оновленні** | Але стан (`useState`) зберігається між рендерами | | React сам оптимізує оновлення DOM | Змінює тільки те, що потрібно | | Не можна напряму змінювати DOM у тілі функції | Тільки в ефектах (`useEffect`, `useLayoutEffect`) | | `useEffect` виконується **після** оновлення DOM (асинхронно) | UI спершу оновиться, потім виконається ефект | | `useLayoutEffect` виконується **до** відмальовування екрана | Для синхронізації розмірів або положення елементів | --- ## Підсумок | Етап | Що робить React | Що робить розробник | |---|---|---| | 1. Зміна даних | Отримує новий `state` або `props` | Викликає `setState` / `setCount` | | 2. Рендер | Заново викликає компонент | Повертає новий JSX | | 3. Diff | Порівнює старий і новий Virtual DOM | Нічого не робить - React сам | | 4. Commit | Оновлює реальний DOM | Можна реагувати в `useEffect` | | 5. Ефекти | Запускає хуки, де змінилися залежності | Виконує побічні дії | --- **Головна ідея:** > При **оновленні** React заново викликає компонент, > перестворює Virtual DOM, порівнює його з попереднім, > оновлює тільки потрібні частини DOM > і запускає ефекти, у яких змінилися залежності.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.