Skip to main content

Що робить useMemo()?

Що робить 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 повертає старе значення
Знижує кількість ререндерівДочірні компоненти не перемальовуються

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.