> Как оптимизировать 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 + useCallback
const 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 с неправильными зависимостями, что приводит к багам или утечкам памяти.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью