ReactJavaScriptFrontend

Как избежать проблем производительности при использовании React.memo

·MAGMA

Почему React.memo не всегда спасает от рендеринга?

В React паттерны вроде React.memo используются разработчиками для предотвращения ненужных повторных рендеров компонентов. Однако есть распространённая ошибка, которая сводит на нет всю оптимизацию.

Проблема inline-пропсов

Когда вы передаёте функции или объекты напрямую через пропсы (props), каждый раз создаётся новая ссылка на объект. Это приводит к тому, что даже если данные внутри объекта остаются неизменными, компонент всё равно будет повторно отображаться, так как React видит новую ссылку.

const MyComponent = () => {
    const handleClick = () => console.log('clicked');
    return <Child onClick={handleClick} />;
};

Здесь функция handleClick создаётся заново при каждом рендеринге родительского компонента, вызывая повторный рендеринг дочернего компонента Child, несмотря на использование React.memo.

Как решить проблему?

Есть несколько способов решения этой проблемы:

Использование useCallback

Функция useCallback позволяет сохранить ссылку на функцию между рендерами, предотвращая создание новой ссылки при каждом обновлении.

import { useCallback } from 'react';

const MyComponent = () => {
    const handleClick = useCallback(() => console.log('clicked'), []);
    return <Child onClick={handleClick} />;
};

Теперь функция handleClick будет создана только один раз, а её ссылка останется прежней до тех пор, пока массив зависимостей пуст.

Избегайте создания объектов в render-функции

Если вам нужно передать объект через пропс, убедитесь, что этот объект создан вне области рендера или используйте мемоизированные значения.

const myObject = { key: 'value' };

const MyComponent = () => (
    <Child objectProp={myObject} />
);

Таким образом, объект будет создан единожды, и его ссылка останется постоянной.

Вернуться к блогу
Оптимизация производительности в React с memo и useCallback — MAGMA