Оптимізація продуктивності JavaScript додатків: useMemo і memo
20.03.2026Вступ: чому продуктивність важлива
У сучасних вебдодатках навіть невеликі затримки у відображенні можуть погіршувати враження користувача. React і схожі бібліотеки прагнуть зробити UI декларативним і ефективним, але при неправильному використанні компонентів і стану можна легко спровокувати зайві перерендери. У цій статті розглянемо, як підходи мемоізації — зокрема memo і useMemo — допомагають оптимізувати продуктивність, і коли їх варто застосовувати.
Що таке мемоізація у контексті JavaScript і React
Мемоізація — це техніка кешування результатів обчислень для повторного використання замість повторного виконання. В загальному JavaScript це може бути збереження результатів тяжкої функції у мапі за ключем з аргументів. У React мемоізація стосується двох основних аспектів:
- Запобігання повторних обчислень у функціональних компонентах (useMemo).
- Запобігання повторним рендерам дочірніх компонентів, якщо їх props не змінилися (React.memo).
useMemo: коли і навіщо
useMemo дозволяє зберегти результат обчислення між рендерами, поки залежності не зміняться. Це корисно, коли маєте важку обчислювальну операцію або формування складного об’єкта, яке виконується під час кожного рендера і привносить значні витрати.
Приклад типових випадків для useMemo:
- Фільтрація або сортування великого масиву даних перед відрисовкою.
- Побудова стабільних об’єктів, які передаються як props у дочірні компоненти.
- Дорога функція математичних або статистичних обчислень.
React.memo: зупиняємо непотрібні рендери
React.memo — це вищий порядок компонент, який мемоізує результат рендеру функціонального компонента. Якщо props не змінилися (поверхневе порівняння), React пропускає рендер компоненту і використовує попередній результат. Це просто і ефективно для компонентів, що рендерять багато UI або мають важку розмітку.
Практичні поради: як використовувати разом
Комбінація useMemo і React.memo часто дає найкращий ефект: memo запобігає ререндам дочірнього компонента, а useMemo гарантує, що props, які передаються, не створюються заново на кожен рендер батька.
- Якщо передаєте в дочірній компонент об’єкт або масив, мемоізуйте його через useMemo, щоб не змінювався при кожному рендері батька.
- Оберніть компонент у React.memo, щоб він рендерився лише при реальних змінах props.
- Для функцій використовуйте useCallback, коли потрібно передати стабільну функцію як prop; технічно це той самий підхід, що і useMemo для функцій.
Приклад поведінки без мемоізації
Уявіть, що батьківський компонент щоразу створює масив items = data.filter(…). Навіть якщо результати фільтрації однакові, посилання на масив змінюється, тому дочірній компонент отримає новий prop і перерендериться. Використання useMemo вирішує цю проблему.
Коли не варто мемоізувати
Мемоізація — не універсальний засіб. Вона додає складність і невеликий наклад на пам’ять і час, потрібний для порівнянь і збереження кешу. Не варто застосовувати memo і useMemo для простих компонентів або коли операції дешеві.
- Не мемоізуйте все підряд. Якщо компонент або обчислення швидкі, наклад може перевищити вигоду.
- Уникайте передчасної оптимізації: спочатку профілюйте додаток, знайдіть вузькі місця, а потім оптимізуйте.
Як вимірювати ефект оптимізації
Перед застосуванням мемоізації перевіряйте реальний вплив. Інструменти для профайлінгу браузера, React DevTools з режимом профайлера і прості логування рендерів допоможуть оцінити, чи зменшились перерендери і загальний час рендера.
Підсумок
useMemo і React.memo — потужні інструменти для підвищення продуктивності React-додатків. Вони допомагають зменшити непотрібні обчислення і рендери, коли використовуються в поміркований і цілеспрямований спосіб. Пам’ятайте: спочатку вимірюйте, потім оптимізуйте, і обирайте мемоізацію там, де є реальна вигода. У поєднанні з грамотною структурою стану та виваженим підходом до передачі props ці прийоми дозволять зробити інтерфейс відчутно швидшим для користувача.