Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить useMemo()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`useMemo()`** - це хук для мемоізації обчисленого значення: він запам'ятовує результат виконання функції між рендерами і повторно обчислює його тільки тоді, коли змінюються залежності. **Ключове:** зберігаючи те саме посилання на об'єкт чи масив між рендерами, `useMemo` дозволяє `React.memo` бачити, що проп не змінився, і уникати зайвих ререндерів дочірніх компонентів.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `useMemo()` Хук `useMemo()` - це **мемоізація обчисленого значення**. Він **запам'ятовує результат виконання функції** між рендерами і **повторно обчислює його тільки тоді**, коли **змінюються залежності**. --- ### Синтаксис ```javascript const memoizedValue = useMemo(() => computeSomething(a, b), [a, b]); ``` - Перший аргумент - функція, яка **повертає результат** (обчислення, фільтрація, сортування тощо). - Другий - масив залежностей `[a, b]`. React запам'ятає результат і при наступному рендері: - якщо залежності **не змінилися** -> поверне **старе значення**; - якщо залежності **змінилися** -> перерахує заново. --- ## Приклад без `useMemo` ```javascript function App({ list }) { const sorted = list.sort(); // кожен рендер - сортування return <List items={sorted} />; } ``` Кожен рендер буде викликати `list.sort()`, і навіть якщо `list` не змінилася - створюється **новий масив**. Якщо `<List />` мемоізований через `React.memo`, він все одно буде ререндеритися, тому що `sorted` -> **нове посилання** (новий об'єкт у пам'яті). --- ## З `useMemo` ```javascript function App({ list }) { const sorted = useMemo(() => [...list].sort(), [list]); return <List items={sorted} />; } ``` Тепер: - Поки `list` не змінилася, React **поверне старе посилання на** `sorted`; - `List` (якщо він `React.memo`) **не буде ререндеритися**; - Це запобігає **зайвим ререндерам і зайвим обчисленням**. --- ## Приклад з обчисленням ```javascript function ExpensiveComponent({ value }) { const heavyResult = useMemo(() => { console.log('expensive calculation'); return fibonacci(value); // припустимо, дорога функція }, [value]); return <div>Result: {heavyResult}</div>; } ``` **Без** `useMemo`**:** - При кожному рендері викликається `fibonacci(value)`, навіть якщо `value` не змінювалася. **З** `useMemo`**:** - Обчислення відбудеться тільки **один раз**, поки `value` залишається тим самим -> React поверне **закешований результат**. --- ## Як `useMemo` допомагає уникнути зайвих ререндерів ### Сценарій: "мемоізована дитина" ```javascript const Child = React.memo(({ data }) => { console.log('Child render'); return <div>{data.length}</div>; }); function Parent({ items }) { const processed = useMemo(() => items.filter(i => i.active), [items]); return <Child data={processed} />; } ``` Якщо `items` не змінилися, -> `processed` залишається **тим самим посиланням** -> `React.memo` розуміє, що проп `data` не змінився -> `Child` **не ререндериться**. Без `useMemo` `processed` створювався б заново, і `Child` **щоразу** перемальовувався б, навіть при незмінних даних. --- ## Що кешує `useMemo` | Тип значення | Кешується? | Приклад | |---|---|---| | Примітиви | Так | `number`, `string`, `boolean` | | Об'єкти та масиви | Так | `const arr = useMemo(() => [...list], [list])` | | Результат функції | Так | `useMemo(() => compute(), [deps])` | | Сама функція | Ні -> для цього `useCallback()` | | > `useCallback(fn, deps)` - це просто скорочення для `useMemo(() => fn, deps)`. --- ## Коли варто використовувати `useMemo` **Використовуй, якщо:** 1. Є **дороге обчислення** (фільтрація, сортування, підрахунки); 2. Потрібно **зберегти посилання** на об'єкт/масив між рендерами (для `React.memo`); 3. Компонент **часто ререндериться**, а залежні дані - рідко змінюються. --- ## Коли **не потрібно** використовувати **Не застосовуй скрізь підряд:** - Якщо обчислення **дешеве** (кілька операцій) - `useMemo` тільки сповільнить (React все одно порівняє deps, створить кеш); - Якщо компонент **все одно ререндериться повністю** (і `useMemo` не бере участі в props інших компонентів); - Якщо дані і так стабільні за посиланням (наприклад, ти не створюєш новий об'єкт щоразу). --- ## Підсумок: useMemo vs useCallback | Хук | Що робить | Повертає | Типова мета | |---|---|---|---| | `useMemo(fn, deps)` | Кешує **результат обчислення** | Значення | Зберегти результат між рендерами | | `useCallback(fn, deps)` | Кешує **функцію** | Функцію | Зберегти посилання на обробник | --- ## Коротко і по суті | Що робить | Як допомагає | |---|---| | Кешує результат обчислень | Уникає повторних важких операцій | | Зберігає посилання на об'єкт/масив | Допомагає `React.memo` побачити, що prop не змінився | | Працює тільки при незмінних залежностях | React повертає старе значення | | Знижує кількість ререндерів | Дочірні компоненти не перемальовуються |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.