Как оптимизировать без useMemo?
Хуки
К useMemo стоит обращаться в последнюю очередь. Почти всё, что он делает, достигается структурными приёмами — часто эффективнее и без хрупкости.
Убрать саму причину лишних рендеров
Спустить состояние вниз. Часто меняющийся state (ввод, hover) держать в маленьком компоненте, а не в корне — соседи вообще не рендерятся.
children как проп. Элементы, созданные выше, стабильны: обёртка со state их не перерисует.
const Panel = ({ children }) => {
const [open, setOpen] = useState(false);
return <div>{open && children}</div>; // children не пересоздаются
};Разделить контексты (данные/действия, частые/редкие) и сузить селекторы стора — обновляются только заинтересованные.
Не создавать лишнего
- Константы и «конфиги» выносить за пределы компонента — тогда ссылка стабильна без useMemo.
- Не хранить производные данные в state (рассинхрон) и не считать заново то, что можно посчитать один раз выше по дереву.
- Функции, не зависящие от рендера, объявлять вне компонента.
Сократить объём работы
- Виртуализация списков (react-window): тысяча строк не окажется в DOM.
- Пагинация, ленивая загрузка (React.lazy), отложенный рендер невидимого.
- useTransition/useDeferredValue: тяжёлое обновление не блокирует ввод (это не мемоизация, но решает ту же боль).
- Дебаунс/throttle дорогих реакций; тяжёлые вычисления — в Web Worker.
И системно
React Compiler (React 19) расставляет мемоизацию сам — ручные useMemo становятся не нужны.
Коротко для собеседования
Без useMemo: спустить состояние вниз, использовать children-как-проп, разделить контексты и сузить селекторы; константы и функции выносить за компонент; сократить работу — виртуализация, пагинация, lazy, useTransition/useDeferredValue, Web Worker. Структурные правки обычно дают больше, чем мемоизация.