Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Рішення про перерисовку компонента». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**React перерисовує (re-render)** компонент, коли змінюється його `state`, `props`, контекст (`context`), або коли перерендерився батьківський компонент і передав нові (чи ті самі, але без оптимізації) `props`. **Ключове:** щоб дочірній компонент не перерендерювався разом з батьківським без потреби, його можна обгорнути в `React.memo()` - тоді він перерендериться лише при зміні `props`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь React **перерисовує компонент (re-render)**, коли: 1. **Змінюється його стан (**`state`**)** 2. **Змінюються його властивості (**`props`**)** 3. **Змінюється контекст (**`context`**)**, якщо він використовується в компоненті 4. **Його батько був перерендерений**, і передав йому **нові props** (або навіть ті самі, але без оптимізації) --- ## 1. Зміна `state` Якщо в компоненті викликається `setState` (або `setCount`, `setUser` тощо), React **запускає повторний рендер цього компонента**. ```javascript function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> {count} </button> ); } ``` Кожен виклик `setCount()` -> React **створює нове Virtual DOM дерево для цього компонента** і **порівнює** його з попереднім (diffing). --- ## 2. Зміна `props` Якщо батьківський компонент передає нові `props`, React **перерендерює дочірній компонент**, щоб відобразити оновлені дані. ```javascript function Greeting({ name }) { return <h1>Привіт, {name}!</h1>; } function App() { const [name, setName] = useState("Alex"); return <Greeting name={name} />; } ``` Коли `setName("Maria")` -> React перерендерить `App`, а потім і `Greeting`, тому що його `props.name` змінилися. --- ## 3. Зміна контексту (`useContext`) Якщо компонент підписаний на контекст через `useContext`, він **перерисується при зміні значення контексту**. ```javascript const ThemeContext = createContext("light"); function Button() { const theme = useContext(ThemeContext); return <button className={theme}>Click</button>; } function App() { const [theme, setTheme] = useState("light"); return ( <ThemeContext.Provider value={theme}> <Button /> </ThemeContext.Provider> ); } ``` `setTheme("dark")` -> усі компоненти, що використовують цей контекст, **перерисуються**. --- ## 4. Коли батько перерендерився Навіть якщо `props` не змінилися за значенням, React все одно **типово перерендерить дочірній компонент**, якщо батько був перерендерений. ```javascript function Child() { console.log("Child render"); return <p>Дитина</p>; } function Parent() { const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(count + 1)}>+</button> <Child /> </> ); } ``` Кожен клік -> `Parent` оновлюється -> `Child` теж **перерендериться**, хоча в нього **немає ні state, ні props**. Щоб цього уникнути, можна обгорнути `Child` в: ```javascript export default React.memo(Child); ``` Тепер React буде ререндерити `Child` **лише якщо змінилися його props**. --- ## Що *не* викликає ререндер Зміна змінних поза `state` ```javascript let count = 0; function Counter() { count++; // React не знає про count - вона не з state } ``` Зміна об'єкта "повз" `setState` ```javascript state.user.name = "Maria"; // React це не відстежить ``` Пряма зміна DOM (`document.querySelector`) React керує своїм Virtual DOM - він не стежить за ручними змінами реального DOM. --- ## Як React вирішує, *що саме* оновити Після того як React вирішує, що компонент має бути перерендерений: 1. Він **знову викликає функцію компонента** (щоб отримати новий JSX). 2. Створює **нове Virtual DOM-дерево**. 3. Порівнює його з попереднім (diffing). 4. **Змінює лише те**, що реально змінилося в реальному DOM (reconciliation). --- ## Оптимізація: коли не потрібно перерендерювати Використовуй `React.memo()` для функціональних компонентів: перерендериться лише при зміні `props`. Використовуй `useMemo()` і `useCallback()`, щоб не пересоздавати функції та обчислення даремно. Передавай **стабільні значення** (id, name тощо), а не нові об'єкти/функції при кожному рендері. --- ## Підсумок | Причина | Компонент перерендериться? | |---|---| | Змінився `state` | Так | | Змінилися `props` | Так | | Змінився контекст | Так | | Батько перерендерився | Так (якщо не `React.memo`) | | Змінилася змінна поза `state` | Ні | | Пряма зміна DOM | Ні |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.