React.Component — базовый класс для создания компонентов с использованием наследования в React. До появления хуков в версии 16.8 классовые компоненты были единственным способом управлять состоянием и жизненным циклом. По данным React, 2024, классовые компоненты по-прежнему поддерживаются, хотя функциональные с хуками рекомендованы для новых проектов.
Главное
React.Component — абстрактный класс, который предоставляет встроенные методы для работы с состоянием, пропсами и жизненным циклом компонента. Чтобы создать классовый компонент, нужно определить класс, наследующий от React.Component, и реализовать метод render.
React.Component появился в самой первой версии React (2013) и оставался основным способом создания компонентов на протяжении пяти лет. Экосистема React строилась вокруг классов: компоненты высшего порядка (HOC), render props, контекст — все эти паттерны были реализованы через классовый синтаксис.
С выходом React 16.8 в 2019 году команда React представила хуки как альтернативу классам. Хуки решали те же задачи — состояние, эффекты, контекст — но без наследования и сложной привязки контекста. React.Component остаётся полностью поддерживаемым, но для новых проектов рекомендуется функциональный подход.
Минимальный классовый компонент — класс с единственным методом render, возвращающим React-элемент. render — единственный обязательный метод. Он должен быть чистой функцией от this.props и this.state: один и тот же набор пропсов и состояния даёт одинаковый результат.
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Конструктор выполняется перед монтированием. В нём вызывается super(props) для передачи пропсов в родительский класс и инициализируется this.state. Использовать конструктор для других целей — подписки, вызовы API — не рекомендуется: для этого есть componentDidMount.
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return <p>Count: {this.state.count}</p>;
}
}
this.state — объект, содержащий данные компонента. Изменять его напрямую (this.state.count = 1) запрещено — это не вызывает ререндер и ломает предсказуемость. Обновлять состояние нужно через this.setState, который создаёт новый объект состояния и запускает повторный рендер.
setState может принимать объект или функцию. Функциональная форма предпочтительна, когда новое состояние зависит от предыдущего: this.setState(prev => ({ count: prev.count + 1 })). React может группировать несколько setState в один батч для оптимизации производительности.
class Toggle extends Component {
constructor(props) {
super(props);
this.state = { isOn: false };
}
handleClick() {
this.setState(prev => ({ isOn: !prev.isOn }));
}
render() {
return (
<button onClick={() => this.handleClick()}>
{this.state.isOn ? 'ON' : 'OFF'}
</button>
);
}
}
Важное свойство setState — он асинхронный. После вызова setState состояние не обновляется мгновенно. Если нужно выполнить действие после обновления, передайте колбэк вторым аргументом: this.setState(newState, () => console.log(this.state)).
Классовые компоненты имеют предопределённые методы, которые React вызывает в определённые моменты. Монтирование — constructor → render → componentDidMount. Обновление — render → componentDidUpdate. Размонтирование — componentWillUnmount.
| Метод | Фаза | Назначение |
|---|---|---|
| constructor | Монтирование | Инициализация state и привязка методов |
| render | Каждый раз | Возврат React-элементов (обязательный) |
| componentDidMount | После монтирования | Запросы API, подписки, таймеры |
| componentDidUpdate | После обновления | Реакция на изменение пропсов/стейта |
| componentWillUnmount | Перед удалением | Очистка подписок, таймеров, отписка от событий |
componentDidMount — основное место для побочных эффектов после первого рендера. Здесь выполняются HTTP-запросы, устанавливаются WebSocket-соединения и стартуют таймеры. Если не очистить подписку в componentWillUnmount, возникает утечка памяти.
class UserProfile extends Component {
componentDidMount() {
fetch(`/api/users/${this.props.userId}`)
.then(res => res.json())
.then(data => this.setState({ user: data }));
}
componentWillUnmount() {
// Cancel request on unmount
}
render() {
return <div>{this.state.user?.name}</div>;
}
}
В JavaScript методы класса по умолчанию не привязаны к экземпляру. Если передать метод как колбэк — в обработчик события, в таймер — this будет undefined (в strict mode) или window (без strict mode). Без привязки this.setState выбросит ошибку.
Существует три способа привязки: bind в конструкторе, стрелочная функция в колбэке и class field со стрелочной функцией. Первый способ — официальная рекомендация React: bind один раз в конструкторе, без пересоздания функции на каждый рендер.
// Method 1: bind in constructor (recommended)
class MyComponent extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ clicked: true });
}
render() {
return <button onClick={this.handleClick}>Click</button>;
}
}
Class field — современный синтаксис с автоматической привязкой. Стрелочная функция в свойстве класса захватывает this из области видимости конструктора. Недостаток — метод создаётся на каждому экземпляре, а не на прототипе, что увеличивает память для сотен компонентов одного типа.
Выбор между классом и функцией — не только вопрос синтаксиса. Функциональные компоненты с хуками решают проблемы, присущие классам: дублирование логики в разных lifecycle-методах (componentDidMount + componentDidUpdate), сложность с this и невозможность извлечь связанную логику в переиспользуемый блок.
Функциональные компоненты легче тестировать — они не имеют внутреннего состояния (которое до хуков было только в классах) и не требуют монтирования в DOM для проверки колбэков. React рекомендует функциональные компоненты для всех новых проектов, документация и примеры пишутся на них.
Классовые компоненты остаются лучшим выбором при работе с легаси-кодом. Если проект начат до 2019 года, в нём, вероятно, тысячи классовых компонентов. Переписывать их все на хуки за один спринт — рискованно. React гарантирует обратную совместимость: классовые компоненты не будут удалены.
Постепенная миграция начинается с анализа компонента. Простые компоненты без состояния (stateless) переводятся первыми — они тривиально заменяются функциями. Затем — компоненты с одним-двумя state-полями, где useState напрямую заменяет this.state и this.setState.
Сложные компоненты с множеством lifecycle-методов переводятся через useEffect. Логика из componentDidMount + componentDidUpdate разбивается на отдельные useEffect с разными зависимостями. componentWillUnmount заменяется return-функцией внутри useEffect. Для сложной логики состояния используйте useReducer.
Инструменты автоматической миграции — @phenomnomnominal/ts-react-class-to-hook или codemod-скрипты — могут автоматически конвертировать простые классы. Для сложных случаев миграция остаётся ручной работой, требующей понимания логики исходного компонента.
Часто задаваемые вопросы
Да. super(props) передаёт пропсы в родительский React.Component. Без этого вызова this.props будет undefined внутри конструктора. В render и lifecycle-методах пропсы доступны даже без super, но это побочное поведение реализации.
React группирует несколько вызовов setState в один батч для уменьшения количества лишних ререндеров. Если бы setState был синхронным, каждый вызов вызывал бы немедленный рендер, снижая производительность при массовых обновлениях.
Нет. Хуки работают только в функциональных компонентах. Для проектов с классовыми компонентами доступны все старые паттерны: render props, HOC и Consumer для контекста. Миграция на хуки требует преобразования класса в функцию.
React.PureComponent реализует shouldComponentUpdate с поверхностным (shallow) сравнением пропсов и состояния. В отличие от Component, который всегда ререндерит при setState, PureComponent пропускает ререндер, если данные не изменились. Это оптимизация для компонентов без сложной вложенности.
Используйте componentDidCatch и getDerivedStateFromError. componentDidCatch(error, info) логирует ошибку. getDerivedStateFromError обновляет state для отображения fallback-UI. Эти методы работают только в классовых компонентах — функциям нужен ErrorBoundary-компонент-обёртка.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также