Состояние и жизненный цикл
These docs are old and won’t be updated. Go to react.dev for the new React docs.
These new documentation pages teach modern React and include live examples:
На этой странице представлены понятия «состояние» (state) и «жизненный цикл» (lifecycle) React-компонентов. Подробный справочник API компонентов находится по этой ссылке.
В качестве примера рассмотрим идущие часы из предыдущего раздела. В главе Рендеринг элементов мы научились обновлять UI только одним способом — вызовом root.render():
const root = ReactDOM.createRoot(document.getElementById('root'));
function tick() {
const element = (
<div>
<h1>Привет, мир!</h1>
<h2>Сейчас {new Date().toLocaleTimeString()}.</h2>
</div>
);
root.render(element);}
setInterval(tick, 1000);В этой главе мы узнаем, как инкапсулировать и обеспечить многократное использование компонента Clock. Компонент самостоятельно установит свой собственный таймер и будет обновляться раз в секунду.
Для начала, извлечём компонент, показывающий время:
const root = ReactDOM.createRoot(document.getElementById('root'));
function Clock(props) {
return (
<div> <h1>Привет, мир!</h1> <h2>Сейчас {props.date.toLocaleTimeString()}.</h2> </div> );
}
function tick() {
root.render(<Clock date={new Date()} />);}
setInterval(tick, 1000);Проблема в том, что компонент Clock не обновляет себя каждую секунду автоматически. Хотелось бы спрятать логику, управляющую таймером, внутри самого компонента Clock.
В идеале мы бы хотели реализовать Clock таким образом, чтобы компонент сам себя обновлял:
root.render(<Clock />);Для этого добавим так называемое «состояние» (state) в компонент Clock.
«Состояние» очень похоже на уже знакомые нам пропсы, отличие в том, что состояние контролируется и доступно только конкретному компоненту.
Преобразование функционального компонента в классовый
Давайте преобразуем функциональный компонент Clock в классовый компонент за 5 шагов:
- Создаём ES6-класс с таким же именем, указываем
React.Componentв качестве родительского класса - Добавим в класс пустой метод
render() - Перенесём тело функции в метод
render() - Заменим
propsнаthis.propsв телеrender() - Удалим оставшееся пустое объявление функции
class Clock extends React.Component {
render() {
return (
<div>
<h1>Привет, мир!</h1>
<h2>Сейчас {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}Теперь Clock определён как класс, а не функция.
Метод render будет вызываться каждый раз, когда происходит обновление. Так как мы рендерим <Clock /> в один и тот же DOM-контейнер, мы используем единственный экземпляр класса Clock — поэтому мы можем задействовать внутреннее состояние и методы жизненного цикла.
Добавим внутреннее состояние в класс
Переместим date из пропсов в состояние в три этапа:
- Заменим
this.props.dateнаthis.state.dateв методеrender():
class Clock extends React.Component {
render() {
return (
<div>
<h1>Привет, мир!</h1>
<h2>Сейчас {this.state.date.toLocaleTimeString()}.</h2> </div>
);
}
}- Добавим конструктор класса, в котором укажем начальное состояние в переменной
this.state:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()}; }
render() {
return (
<div>
<h1>Привет, мир!</h1>
<h2>Сейчас {this.state.date.toLocaleTimeString()}.</h2>
</div>
)