React·100 вопросов

Что такое React.memo и как он работает?

Ответ

Инструмент React.memo представляет собой функцию высшего порядка, которая позволяет оптимизировать рендеринг функциональных компонентов в приложениях на React. Принцип его работы заключается в том, что он оборачивает ваш компонент и возвращает его мемоизированную версию. Когда родительский компонент обновляется и пытается передать новые данные, React.memo перехватывает этот процесс и сравнивает новые пропсы со старыми, принимая решение о необходимости повторного запуска функции компонента.

Механизм сравнения пропсов в React.memo по умолчанию основан на поверхностном сравнении, которое в англоязычной литературе называется shallow comparison. Это означает, что React сравнивает примитивные значения по их содержимому, а сложные типы данных, такие как объекты и массивы, — исключительно по ссылкам в памяти. Если ссылка на объект изменилась, даже если его внутренние свойства остались прежними, React сочтет пропсы измененными и инициирует полноценный повторный рендеринг компонента.

Для нестандартных сценариев разработчики могут передать в качестве второго аргумента в React.memo кастомную функцию сравнения, которая принимает предыдущие и текущие пропсы. Алгоритм действий выглядит следующим образом:

Написать функцию areEqual(prevProps, nextProps), возвращающую true, если пропсы равны, и false, если они различаются.
Передать эту функцию вторым параметром: export default React.memo(MyComponent, areEqual).
Использовать кастомное сравнение осторожно, так как сложная логика внутри функции сравнения может работать дольше, чем сам рендеринг компонента.

Чтобы стандартный поверхностный алгоритм сравнения работал эффективно, необходимо стабилизировать ссылки на передаваемые пропсы. Для этого разработчики активно используют хуки useMemo для объектов и массивов, а также useCallback для функций, передаваемых из родительского компонента. Без этой предварительной стабилизации оборачивание компонентов в React.memo не принесет абсолютно никакой практической пользы, так как ссылки на пропсы будут постоянно обновляться при каждом рендере родителя.

Важнейшей особенностью работы React.memo является его полная бессилие перед изменениями контекста React. Если мемоизированный компонент внутри своего тела или среди дочерних элементов подписывается на контекст через хук useContext, то любое изменение этого контекста вызовет принудительный ререндер компонента. Это происходит независимо от того, изменились ли пропсы, переданные через родительский компонент, и этот нюанс обязательно нужно учитывать при проектировании архитектуры глобального состояния приложения.

Полезен ли этот ответ?

Другие вопросы этой темы

Связанные вопросы из других тем