useMemo, useCallback та React.memo у React: Коли їх варто використовувати
Оптимізація продуктивності — це одна з ключових задач для розробників React-додатків. Інструменти useMemo
, useCallback
і React.memo
допомагають уникнути зайвих рендерів компонентів та економити ресурси браузера. Розглянемо, як і коли доцільно їх використовувати.
Що таке useMemo
?
Хук useMemo
дозволяє кешувати результат обчислень, щоб не виконувати їх при кожному рендері.
Приклад використання
Припустимо, у вас є функція для виконання важких обчислень:
import { useMemo } from 'react';
function ExpensiveComponent({ num }) {
const result = useMemo(() => {
console.log('Обчислення...');
return num ** 2;
}, [num]);
return <div>Результат: {result}</div>;
}
Коли використовувати?
- Коли обчислення складні або залежать від великого обсягу даних.
- Коли рендеринг без
useMemo
призводить до значного зниження продуктивності.
Що таке useCallback
?
useCallback
кешує функції, щоб їхні посилання не змінювалися між рендерами.
Приклад використання
Використання в парі з дочірнім компонентом:
import { useState, useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<Child onClick={handleClick} />
<p>Клікнуто {count} разів</p>
</div>
);
}
function Child({ onClick }) {
console.log('Child рендериться');
return <button onClick={onClick}>Клікни мене</button>;
}
Коли використовувати?
- Коли функції передаються як пропси в дочірні компоненти.
- У поєднанні з
React.memo
для уникнення зайвих рендерів.
Що таке React.memo
?
React.memo
— це HOC (Higher-Order Component), який запобігає повторному рендеру компонента, якщо його пропси не змінилися.
Приклад використання
import React from 'react';
const MemoizedChild = React.memo(function Child({ value }) {
console.log('Child рендериться');
return <div>{value}</div>;
});
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<MemoizedChild value="Статичний текст" />
<button onClick={() => setCount(count + 1)}>Збільшити</button>
</div>
);
}
Коли використовувати?
- Для компонентів, які рідко змінюють свої пропси.
- Коли уникнення зайвого рендеру дає помітний приріст продуктивності.
Взаємодія між useMemo
, useCallback
та React.memo
Ці три інструменти часто використовуються разом:
useCallback
створює кешовану функцію.useMemo
оптимізує обчислення.React.memo
зменшує кількість рендерів компонентів.
Комбінований приклад
function Parent() {
const [count, setCount] = useState(0);
const expensiveCalculation = useMemo(() => {
console.log('Виконуємо обчислення...');
return count ** 2;
}, [count]);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<MemoizedChild value={expensiveCalculation} onClick={handleClick} />
</div>
);
}
const MemoizedChild = React.memo(({ value, onClick }) => {
console.log('Child рендериться');
return <div onClick={onClick}>Результат: {value}</div>;
});
Коли не використовувати ці інструменти?
useMemo
таuseCallback
: Якщо кешування дає більше витрат на пам’ять, ніж виграш у продуктивності.React.memo
: Якщо компонент рендериться швидко і без оптимізації.
Висновок
Оптимізація React-додатків з useMemo
, useCallback
та React.memo
може значно покращити продуктивність, особливо у складних інтерфейсах. Проте їхнє використання має бути обґрунтованим: надмірна оптимізація може ускладнити код і не дати значного ефекту.