> Какие жизненные циклы есть у классовых компонентов и как они реализованы в функциональных (React)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Сбер
Стек: React
> Пример ответа
Короткий ответ
У классовых компонентов три фазы жизненного цикла: монтирование (constructor, render, componentDidMount), обновление (shouldComponentUpdate, render, componentDidUpdate) и размонтирование (componentWillUnmount). В функциональных компонентах они реализованы через хуки: useState и useEffect с массивами зависимостей имитируют componentDidMount ([]), componentDidUpdate (без зависимостей или с конкретными) и componentWillUnmount (return cleanup). useMemo и useCallback заменяют shouldComponentUpdate.
Подробное объяснение
Классовые компоненты React имеют четко определенные методы жизненного цикла, которые вызываются в определенные моменты:
- Монтирование: constructor → static getDerivedStateFromProps → render → componentDidMount
- Обновление: static getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate
- Размонтирование: componentWillUnmount
Функциональные компоненты используют хуки для эмуляции этих фаз:
- useEffect с [] - выполняется после первого рендера, аналог componentDidMount
- useEffect без зависимостей - выполняется после каждого рендера, аналог componentDidUpdate (но не идентичен, так как вызывается после рендера, а не до)
- useEffect с return cleanup - cleanup функция вызывается при размонтировании, аналог componentWillUnmount
- useMemo - мемоизация вычислений, частично заменяет shouldComponentUpdate
- useCallback - мемоизация функций
Ключевое отличие: в функциональных компонентах эффекты объединяют несколько фаз в один хук, что упрощает код, но требует понимания порядка выполнения. useEffect всегда выполняется после рендера, в то время как componentDidUpdate вызывается синхронно после обновления.
На практике
Для замены componentDidMount используйте useEffect с пустым массивом зависимостей. Для componentDidUpdate - useEffect с конкретными зависимостями или без них. Для componentWillUnmount - return функцию внутри useEffect. Избегайте использования useEffect без зависимостей для логики, которая должна выполняться только при монтировании - это приведет к повторным вызовам.
Для оптимизации производительности используйте useMemo и useCallback вместо shouldComponentUpdate, но помните, что они не предотвращают рендер, а только мемоизируют значения. Для предотвращения лишних рендеров используйте React.memo.
Пример кода
JSX// Классовый компонентclass UserProfile extends React.Component {componentDidMount() {fetchUser(this.props.id);}componentDidUpdate(prevProps) {if (prevProps.id !== this.props.id) {fetchUser(this.props.id);}}componentWillUnmount() {cleanup();}render() {return <div>{this.props.name}</div>;}}// Функциональный компонентfunction UserProfile({ id, name }) {useEffect(() => {fetchUser(id);return () => cleanup();}, [id]); // выполняется при монтировании и при изменении idreturn <div>{name}</div>;}
Как отвечать на собеседовании
Начните с перечисления фаз жизненного цикла классовых компонентов, затем объясните, как каждый метод заменяется хуками. Упомяните, что useEffect объединяет componentDidMount, componentDidUpdate и componentWillUnmount. Подчеркните разницу в порядке выполнения: в классовом компоненте методы вызываются синхронно, в функциональном - асинхронно после рендера. Приведите пример с зависимостями и cleanup функцией.
Что проверяет интервьюер
Интервьюер оценивает понимание эволюции React от классовых к функциональным компонентам, знание тонкостей работы хуков (особенно порядка выполнения эффектов), умение правильно выбирать зависимости для useEffect, понимание trade-off между подходами. Также проверяется способность объяснить, почему функциональные компоненты с хуками считаются более предсказуемыми и тестируемыми.
Типичные ошибки
- Использование useEffect без зависимостей для логики, которая должна выполняться только при монтировании - это приводит к повторным вызовам при каждом ререндере
- Путаница между componentDidUpdate и useEffect: useEffect не блокирует рендер, а выполняется после него
- Забывание cleanup функции для отписки от событий или отмены запросов
- Использование useMemo и useCallback без необходимости - это добавляет overhead и усложняет код
- Попытка напрямую заменить shouldComponentUpdate на useEffect - это разные концепции
> Похожие задачи по frontend
Как происходит оптимизация с виртуальным деревом в React
Как реализовать построение полного маршрута из массива билетов в React
Нужно ли мемоизировать данные, полученные из Redux селектора в компоненте
Как реализовать кастомные алгоритмы в компонентах Material UI
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью