В чем разница между useMemo и react.memo и useCallback?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между useMemo и React.memo и useCallback?
Эти три хука/функции решают проблему оптимизации производительности в React, но каждый работает на разных уровнях и решает разные задачи.
React.memo — мемоизация компонента
React.memo — это функция высшего порядка (HOC), которая мемоизирует весь компонент. Она предотвращает повторный рендер компонента, если его props остались неизменными.
// Без оптимизации: компонент перерендерится при каждом рендере родителя
function MyComponent({ name, value }) {
return <div>{name}: {value}</div>;
}
// С React.memo: компонент перерендерится только при изменении props
const MemoizedComponent = React.memo(function MyComponent({ name, value }) {
return <div>{name}: {value}</div>;
});
// Использование пользовательского сравнения props
const MemoizedComponent = React.memo(
MyComponent,
(prevProps, nextProps) => {
// Вернуть true, если props равны (компонент не перерендеривается)
// Вернуть false, если props изменились (компонент перерендеривается)
return prevProps.name === nextProps.name;
}
);
useMemo — мемоизация значения
useMemo — это хук, который мемоизирует результат дорогостоящего вычисления. Это полезно, когда вычисление требует больших затрат времени и процессора.
const memoizedValue = useMemo(() => {
return expensiveCalculation(value);
}, [value]); // Зависимости
// Пример: сложные вычисления
function FilteredList({ items, searchTerm }) {
const filteredItems = useMemo(() => {
console.log("Выполняю фильтрацию...");
return items.filter(item => item.includes(searchTerm));
}, [items, searchTerm]);
return (
<ul>
{filteredItems.map(item => <li key={item}>{item}</li>)}
</ul>
);
}
// Без useMemo: фильтрация выполнится при каждом рендере
// С useMemo: фильтрация выполнится только при изменении items или searchTerm
useCallback — мемоизация функции
useCallback — это хук, который мемоизирует функцию. Это полезно, когда функция передается как prop дочерним компонентам, обёрнутым в React.memo.
const memoizedCallback = useCallback(() => {
doSomething(value);
}, [value]); // Зависимости
// Пример: обработчик события
function Parent() {
const [count, setCount] = React.useState(0);
// Без useCallback: handleClick создается при каждом рендере
// Это заставит Child перерендериться, даже если его другие props не изменились
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return <Child onClick={handleClick} />;
}
const Child = React.memo(({ onClick }) => {
return <button onClick={onClick}>Нажми меня</button>;
});
Сравнение в таблице
| Инструмент | Что оптимизирует | Применение | Зависимости |
|---|---|---|---|
| React.memo | Весь компонент | Предотвращение повторных рендеров компонента | Сравнение props |
| useMemo | Результат вычисления | Кеширование дорогостоящих расчётов | Массив зависимостей |
| useCallback | Функция | Стабилизация функций для дочерних компонентов | Массив зависимостей |
Лучшие практики
// 1. Используй React.memo для дочерних компонентов, которые получают props
const ChildComponent = React.memo(function Child({ data, onClick }) {
return <button onClick={onClick}>{data}</button>;
});
// 2. Используй useCallback для передачи функций в React.memo компоненты
function Parent() {
const handleClick = useCallback(() => {
// ...
}, []);
return <ChildComponent onClick={handleClick} />;
}
// 3. Используй useMemo для дорогостоящих вычислений
function ExpensiveComponent({ data }) {
const processedData = useMemo(
() => complexAlgorithm(data),
[data]
);
return <div>{processedData}</div>;
}
// 4. Не переоптимизируй — вначале профилируй!
// Используй React DevTools Profiler для анализа производительности
Когда использовать
React.memo: когда компонент часто перерендеривается с одинаковыми props
useMemo: когда вычисление занимает заметное время (сортировка большого массива, сложные расчёты)
useCallback: когда вы передаёте функцию в React.memo компонент или используете её как зависимость в другом хуке
Важно помнить, что оптимизация имеет цену: каждый хук занимает память. Оптимизируй только по необходимости, предварительно профилировав приложение!