Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «memo() і стан». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`React.memo()`** - це функція вищого порядку (HOC), яка "обгортає" функціональний компонент і каже React: якщо пропси не змінилися, не перемальовувати цей компонент заново. **Ключове:** `React.memo()` запобігає зайвим ререндерам дочірніх компонентів, коли стан батьківського компонента змінюється, але не впливає на їхні пропси.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `React.memo()` `React.memo()` - це **функція вищого порядку (HOC)**, яка "обгортає" функціональний компонент і каже React: > "Якщо пропси не змінилися - не перемальовуй цей компонент заново." --- ### Синтаксис ```javascript const MyComponent = React.memo(function MyComponent(props) { // ... }); ``` або у стрілковій формі: ```javascript const MyComponent = React.memo((props) => { // ... }); ``` --- ## Як працює `React.memo()` Зазвичай React **перемальовує компонент при кожному рендері батька**, навіть якщо його `props` не змінилися. `React.memo()` робить наступне: 1. Зберігає **попередні пропси** компонента. 2. При наступному рендері **порівнює нові та старі пропси** (поверхнево). 3. Якщо пропси **не змінилися за посиланням** -> компонент **не ререндериться**. 4. Якщо хоча б один проп змінився -> компонент **перемальовується**. --- ### Без `React.memo()` ```javascript function Child({ value }) { console.log("Child ререндер"); return <p>{value}</p>; } function Parent() { const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(c => c + 1)}>+</button> <Child value="static text" /> </> ); } ``` Щоразу при кліку `Parent` ререндериться, і `Child` **теж ререндериться**, хоча його `props` не змінюються. --- ### З `React.memo()` ```javascript const Child = React.memo(function Child({ value }) { console.log("Child ререндер"); return <p>{value}</p>; }); ``` Тепер `Child` **не ререндериться**, поки його пропси (`value`) не зміняться. Продуктивність зростає, особливо при списках, таблицях і великих деревах компонентів. --- ## Як це пов'язано зі станом 1. Коли ти викликаєш `setState` у батьківському компоненті -> React **ререндерить батька**. 2. За замовчуванням усі **дочірні компоненти** ререндеряться теж. 3. `React.memo()` запобігає цим "зайвим" ререндерам, якщо дочірні компоненти **не залежать від зміненого стану** батька. --- ### Приклад ```javascript function Parent() { const [count, setCount] = useState(0); const [text, setText] = useState(""); return ( <div> <input value={text} onChange={e => setText(e.target.value)} /> <Counter count={count} /> <button onClick={() => setCount(c => c + 1)}>+</button> </div> ); } const Counter = React.memo(({ count }) => { console.log("Counter ререндер"); return <p>Лічильник: {count}</p>; }); ``` Під час введення тексту `Counter` **не ререндериться**, тому що `count` (його проп) не змінився. Без `React.memo()` ререндер відбувався б на кожен ввід. --- ## Важливо: поверхневе порівняння (shallow compare) React.memo() **порівнює пропси за посиланням**, не глибоко. Приклад: ```javascript const user = { name: "Tim" }; <Child data={user} /> ``` Якщо при наступному рендері створюється **новий об'єкт**: ```javascript <Child data={{ name: "Tim" }} /> ``` React.memo **все одно перемалює компонент**, тому що `{} !== {}` (різні посилання в пам'яті). Щоб цього уникнути, мемоізуй об'єкти та функції через: ```javascript useMemo() / useCallback() ``` --- ## Комбінація `React.memo` + `useCallback` / `useMemo` Дуже часто `React.memo` використовується разом з мемоізацією колбеків: ```javascript const handleClick = useCallback(() => { console.log("clicked"); }, []); // посилання не змінюється між рендерами <Child onClick={handleClick} /> ``` Без `useCallback` React буде створювати нову функцію на кожен рендер, і `React.memo` не допоможе, тому що пропси будуть "новими" щоразу. --- ## Підсумок | Що робить `React.memo()` | Обгортає компонент, щоб він **ререндерився тільки при зміні пропсів** | |---|---| | Як працює | Поверхнево порівнює старі та нові пропси | | Зв'язок зі станом | Запобігає ререндеру дочірніх компонентів, якщо стан батька не впливає на їхні пропси | | Ключові інструменти поруч | `useCallback`, `useMemo` - щоб зберігати стабільні посилання | | Коли застосовувати | При великих деревах, таблицях, списках, важких дочірніх компонентах | | Коли не потрібен | У простих компонентах - React сам достатньо оптимізований |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.