> Как оптимизировать React компонент, чтобы Child компонент не перерендеривался при вводе текста? (React)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Т-Банк
Стек: React
> Пример ответа
Короткий ответ
Чтобы Child не перерендеривался при вводе текста, используй React.memo для мемоизации компонента, передавай только стабильные пропсы (без новых функций или объектов на каждый render) и вынеси состояние ввода в родительский компонент, не передавая его в Child. Для колбэков используй useCallback, для значений - useMemo.
Подробное объяснение
Проблема возникает из-за того, что при каждом изменении текста в input родительский компонент перерендеривается, создавая новые ссылки на функции и объекты, передаваемые в Child. React по умолчанию перерендеривает все дочерние компоненты, даже если их пропсы не изменились по значению, но изменились по ссылке.
Основные техники оптимизации:
- React.memo - оборачивает компонент и выполняет поверхностное сравнение пропсов. Если пропсы не изменились (по ссылке), компонент не перерендеривается.
- useCallback - мемоизирует функции-колбэки, чтобы их ссылка оставалась стабильной между рендерами.
- useMemo - мемоизирует вычисляемые значения или объекты.
- Вынос состояния - если Child не зависит от вводимого текста, можно вынести input в отдельный компонент, а Child оставить без этого состояния.
Важно понимать trade-off: мемоизация сама по себе имеет стоимость (сравнение пропсов, хранение кэша). Применяй её только когда перерендеры действительно создают проблемы производительности, а не превентивно.
На практике
На собеседовании senior ожидают, что ты не просто назовёшь React.memo, но и объяснишь, почему он может не сработать. Например, если в пропсах передаётся объект style={{ color: 'red' }} - это новый объект на каждый render, и React.memo не поможет. Нужно либо вынести объект в константу вне компонента, либо обернуть в useMemo.
Также важно упомянуть, что React.memo использует shallow compare. Если в пропсах есть вложенные объекты или массивы, нужно передать второй аргумент - функцию сравнения, но это редкий кейс и обычно сигнал, что архитектура страдает.
Для классовых компонентов аналог - PureComponent или shouldComponentUpdate.
Пример кода
JSX// Плохо - Child перерендеривается при каждом вводеfunction Parent() {const [text, setText] = useState('');return (<><input value={text} onChange={e => setText(e.target.value)} /><Child onClick={() => console.log('click')} /></>);}// Хорошо - используем React.memo + useCallbackconst Child = React.memo(({ onClick }) => {return <button onClick={onClick}>Click</button>;});function Parent() {const [text, setText] = useState('');const handleClick = useCallback(() => console.log('click'), []);return (<><input value={text} onChange={e => setText(e.target.value)} /><Child onClick={handleClick} /></>);}
Как отвечать на собеседовании
Начни с React.memo как базового решения, затем добавь про стабильность пропсов через useCallback/useMemo. Объясни, почему без них React.memo бесполезен. Упомяни, что если Child не использует никакие пропсы из родителя, можно вынести его в константу вне компонента - он вообще не будет перерендериваться. Покажи понимание, когда мемоизация избыточна: для простых компонентов без тяжёлых вычислений она только ухудшит производительность.
Что проверяет интервьюер
- Понимание механизма ререндера в React и роли ссылочной идентичности.
- Умение применять React.memo, useCallback, useMemo в правильных сценариях.
- Осознание trade-off между мемоизацией и производительностью.
- Способность диагностировать, почему мемоизация не сработала (например, из-за children-пропса или контекста).
Типичные ошибки
- Использование React.memo без стабилизации пропсов - мемоизация не работает.
- Мемоизация всего подряд без анализа реальных проблем производительности.
- Передача анонимных функций или объектов в пропсы даже после оборачивания в React.memo.
- Забывание, что React.memo не работает с пропсами-компонентами (children) - они всегда новые.
- Использование useCallback/useMemo с неправильными зависимостями, что приводит к багам или утечкам памяти.
> Похожие задачи по frontend
Как реализовать кастомные алгоритмы в компонентах Material UI
Как передать данные с одного микрофронтенда на другой в React?
Почему React-компонент может вызываться два раза подряд?
Что такое forwardRef в React и для чего он используется?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью