> Как использовать memo в React для предотвращения лишних рендеров (React)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Centicore
Стек: React
> Пример ответа
Короткий ответ
React.memo - это higher-order component, который предотвращает повторный рендер компонента, если его props не изменились (поверхностное сравнение). Используется для оптимизации производительности, когда компонент часто перерисовывается с одними и теми же props. Важно применять только к чистым компонентам без side effects и не злоупотреблять, так как само сравнение имеет стоимость.
Подробное объяснение
React.memo работает путём кэширования результата рендера компонента. При каждом обновлении родителя React выполняет поверхностное сравнение (shallow comparison) предыдущих и новых props. Если они равны, React переиспользует закешированный результат, пропуская рендер компонента.
Механизм сравнения можно кастомизировать через второй аргумент - функцию areEqual(prevProps, nextProps), возвращающую true если props равны.
Важно понимать, что React.memo не влияет на состояние или контекст - если компонент использует useState, useReducer или useContext, он всё равно будет перерендериваться при их изменении.
Ключевые случаи для применения:
- Компоненты, которые рендерятся часто (например, в списках)
- Компоненты с тяжёлыми вычислениями
- Компоненты, которые не зависят от часто меняющихся данных
На практике
Применять React.memo стоит после профилирования и выявления узких мест. Типичный сценарий - оптимизация списков с key и стабильными ссылками на props. Важно помнить, что если передавать в props объекты, функции или массивы без useMemo/useCallback, React.memo будет бесполезен - каждое создание новой ссылки приведёт к перерендеру.
Хорошая практика - оборачивать в React.memo компоненты, которые:
- Являются листьями дерева компонентов
- Имеют стабильные props (примитивы или мемоизированные значения)
- Используются в циклических рендерах (списки, таблицы)
Пример кода
JSXimport React, { memo, useState, useCallback } from 'react';// Компонент, обёрнутый в memoconst ExpensiveItem = memo(({ title, onSelect }) => {console.log('ExpensiveItem render:', title);return (<div onClick={() => onSelect(title)}>{title}</div>);});// Родительский компонентfunction List() {const [items, setItems] = useState(['a', 'b', 'c']);const [count, setCount] = useState(0);// Стабильная ссылка на callbackconst handleSelect = useCallback((title) => {console.log('Selected:', title);}, []);return (<div><button onClick={() => setCount(c => c + 1)}>Count: {count}</button>{items.map(item => (<ExpensiveItemkey={item}title={item}onSelect={handleSelect}/>))}</div>);}
Как отвечать на собеседовании
Начни с определения и цели React.memo. Объясни механизм поверхностного сравнения и когда это действительно нужно. Покажи понимание trade-off: сравнение props имеет стоимость, поэтому React.memo не панацея. Упомяни связь с useMemo и useCallback для стабильных ссылок. Приведи пример из практики - оптимизация списка с тысячей элементов. Подчеркни, что преждевременная оптимизация вредна, и нужно профилировать.
Что проверяет интервьюер
- Понимание механизма рендеринга React и виртуального DOM
- Знание разницы между
React.memo,useMemoиuseCallback - Умение оценивать необходимость оптимизации
- Понимание поверхностного сравнения и его ограничений
- Знание, что
React.memoне работает с контекстом и состоянием - Способность объяснить trade-off между производительностью и читаемостью
Типичные ошибки
- Оборачивание всех компонентов подряд без профилирования
- Передача анонимных функций или объектов как props (ломает мемоизацию)
- Использование
React.memoс компонентами, имеющими side effects в рендере - Забывание про
keyпри рендере списков - Ожидание, что
React.memoпредотвратит рендер при изменении контекста - Использование кастомной
areEqualбез понимания её влияния на производительность
> Похожие задачи по frontend
Нужно ли использовать useMemo или useRef для хранения статичных данных в React?
Зачем использовать setState с колбэком в React?
Как React отслеживает количество вызовов хуков между рендерами?
Что такое shallowRef и shallowReactive и каково их назначение во Vue
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью