← Назад к вопросам
Как работает memo?
1.7 Middle🔥 171 комментариев
#React#Оптимизация и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает React.memo
React.memo — это HOC (Higher Order Component), который оптимизирует производительность компонента путём мемоизации. Компонент перерендеривается только если его props изменились.
Базовое использование
const MyComponent = ({ name, age }: Props) => {
console.log("Компонент отрендерился");
return <div>{name}, {age}</div>;
};
export default React.memo(MyComponent);
При перерендере родителя, если props не изменились, React пропустит перерендер дочернего компонента.
Как работает сравнение props
По умолчанию React.memo использует поверхностное сравнение (shallow comparison):
const obj1 = { value: 42 };
const obj2 = { value: 42 };
console.log(obj1 === obj2); // false — разные ссылки
Это проблема для объектов и функций, потому что новый объект создаётся на каждом рендере:
const Parent = () => {
const user = { name: "Alice" }; // новый объект каждый раз!
return <Child user={user} />; // memo видит новый props
};
const Child = React.memo(({ user }: Props) => {
console.log("Child отрендерился"); // выполнится каждый раз!
return <div>{user.name}</div>;
});
Решение 1: useMemo для объектов
const Parent = () => {
const user = useMemo(() => ({ name: "Alice" }), []);
return <Child user={user} />;
};
Решение 2: useCallback для функций
const Parent = () => {
const handleClick = useCallback(() => {
console.log("Clicked");
}, []); // зависимости
return <Child onClick={handleClick} />;
};
Решение 3: Кастомная функция сравнения
Второй параметр memo — функция сравнения. Верни true если props «равны»:
const MyComponent = ({ user, settings }: Props) => {
return <div>{user.name}</div>;
};
const arePropsEqual = (prevProps, nextProps) => {
// Вернуть true = пропустить перерендер
// Вернуть false = выполнить перерендер
return prevProps.user.id === nextProps.user.id;
};
export default React.memo(MyComponent, arePropsEqual);
Практический пример: List с memo
interface ItemProps {
id: number;
name: string;
onDelete: (id: number) => void;
}
const ListItem = React.memo(({ id, name, onDelete }: ItemProps) => {
console.log(`Item ${id} rendered`);
return (
<li>
{name}
<button onClick={() => onDelete(id)}>Удалить</button>
</li>
);
});
const List = ({ items }: { items: Item[] }) => {
const handleDelete = useCallback((id: number) => {
// удалить элемент
}, []);
return (
<ul>
{items.map(item => (
<ListItem
key={item.id}
id={item.id}
name={item.name}
onDelete={handleDelete} // useCallback! иначе новая функция каждый раз
/>
))}
</ul>
);
};
Когда memo помогает
- Тяжёлые компоненты с дорогими вычислениями
- Списки с сотнями элементов
- Чистые компоненты (pure components), которые зависят только от props
- Часто обновляемые родители (Input, Slider, Animation)
Когда memo не поможет
- Если родитель обновляется часто и всегда передаёт новые props
- Если забыл обернуть в useMemo/useCallback объекты и функции
- Если компонент маленький (переделать не стоит)
- Если используешь render props или children (всегда новые ссылки)
Профилирование перерендеров
const Child = React.memo(({ name }: Props) => {
console.log("Child rendered", name);
return <div>{name}</div>;
}, (prevProps, nextProps) => {
const equal = prevProps.name === nextProps.name;
console.log(`Props equal: ${equal}`);
return equal;
});
Важные моменты
- Не оверюзь memo — микрооптимизация может замедлить разработку
- Используй React DevTools Profiler для анализа перерендеров
- memo + useMemo + useCallback = комбо для максимальной оптимизации списков