Как оптимизировать компонент Child, чтобы он не ререндерился при наборе текста в инпуте
Что проверяют
Понимаете ли вы, почему Child вообще ререндерится: не из-за пропсов, а потому что ререндерится родитель, где живёт состояние инпута. Следом обычно просят объяснить, почему React.memo не сработал, если в Child передаётся обработчик или объект.
Как отвечать
Сначала механика: setState перерисовывает компонент и по умолчанию всех его потомков, независимо от того, изменились ли их пропсы. Ререндер это вызов функции компонента и сравнение результата, в DOM попадают только реальные отличия. Дальше способы в порядке предпочтения:
- опустить состояние вниз: вынести инпут вместе с его
useStateв отдельный компонент. Родитель при наборе больше не перерисовывается, а значит, и Child. Самое простое и самое правильное решение; - композиция через
children: компонент с состоянием принимает Child какchildren. Элемент создан выше и между рендерами остаётся тем же объектом, поэтому React его пропускает; React.memoи стабильные пропсы: если состояние перенести нельзя, Child оборачивают вmemo, а функции и объекты для него стабилизируют черезuseCallbackиuseMemo. ИнлайнonClick={() => ...}илиstyle={{}}ломает мемоизацию на каждом рендере;- неконтролируемый инпут:
defaultValueи чтение черезrefилиFormDataпри отправке, если значение нужно только в конце; useDeferredValue: если Child зависит от текста и тяжёлый, ререндер останется, но перестанет тормозить ввод.
Упомяните React Compiler: когда он включён, мемоизация компонентов и значений происходит автоматически, и ручные useMemo нужны реже. Результат проверяйте в Profiler из React DevTools, а не на глаз.
Где спотыкаются
Оборачивают Child в memo, но передают ему новую функцию или объект на каждом рендере. Сравнение пропсов проваливается, и оптимизации нет.
Расставляют useCallback в родителе, не обернув Child в memo. Стабильная ссылка сама по себе ререндер не отменяет.
Забывают про контекст. Если Child читает контекст, значение которого меняется при вводе, memo не поможет: нужно разделить контекст или вынести из него состояние.