Увидев useMemo впервые, я подумал, что этот хук связан исключительно с кэшированием. Как и многие разработчики, предположил, что его цель — оптимизация производительности, предотвращение ненужных повторных вычислений в компоненте React. Но, проработав с React пять лет, пришел к выводу: истинная мощь useMemo заключается в другом — в стабильности и обеспечении предсказуемого поведения.
useMemo считают некой волшебной палочкой для повышения производительности посредством мемоизации значений. Технически это так, однако реально полезен useMemo недопущением повторного создания ссылок, чреватых малозаметными багами, особенно в хуках или пропсах, которые зависят от стабильных данных.
Разберем конкретно мой случай.
Момент осознания: корректное использование useMemo
Создавая пользовательский хук для динамических вычислений, я изначально передавал в него объект, которому требовалось объединение имеющихся полей и значений. Ради простоты этот объект создавался встроенным:
const existingFields = {
...bookingFields,
...values,
};
const { calculations } = useCalculations(existingFields);
На первый взгляд, все безобидно. Но вскоре я заметил, что компонент бесконечно перерисовывается, а вычисления нестабильны: объект existingFields воссоздавался при каждой отрисовке, даже если его содержимое не менялось. Объекты в React сравниваются по ссылке, поэтому хук «думал», что данные каждый раз менялись.
useMemo в деле
Здесь и приходится кстати useMemo. Оборачиванием в него existingFields обеспечивается, что этот объект вычислится повторно только при изменении своих зависимостей:
const existingFields = useMemo(
() => ({
...bookingFields,
...values,
}),
[bookingFields, values]
);
Этим простым изменением ссылка стабилизировалась, и пользовательский хук, наконец, вернулся к целевому поведению. С лишними переотрисовками покончено.
Когда использовать useMemo
- При передаче производных объектов или массивов в качестве зависимостей хукам или пропсам — во избежание ненужных отрисовок.
- При сравнении в React зависимостей, например, в
useEffectилиuseCallback— для стабилизации зависимостей. - Если получение значения дорого вычислительно, с
useMemoоно вычисляется повторно только при необходимости — для сложных вычислений.
Когда не использовать useMemo
Не прибегайте к useMemo преждевременно. Вычисления тривиальные или не зависимые от других пропсов или состояний пропускаются. Злоупотребление useMemo при отсутствии существенных выгод от этого чревато затруднением восприятия кода.
Заключение
useMemo — мощный инструмент, но его реальное назначение не ограничивается кэшированием. Это еще и стабилизация ссылок во избежание малозаметных багов, особенно в хуках и компонентах React. Фокусируясь на этом аспекте, вы не только напишете более предсказуемый код, но и повысите производительность приложения в действительно важных отношениях.
Поэтому, когда в следующий раз понадобится useMemo, задайтесь вопросом: «Стабилизирую ли я значение во избежание лишней работы или просто пытаюсь провести преждевременную оптимизацию?»
Читайте также:
- 7 React-проектов, которые помогут вам стать лучшим разработчиком
- 70% интервьюеров задают эти 5 вопросов по React.js
- Топ-25 полезных советов для React-разработчиков. Часть 2
Читайте нас в Telegram, VK и Дзен
Перевод статьи Piyush Dubey: After 5 Years with React, I Finally Understood useMemo (Hint: It’s Not About Caching)





