Этот сайт больше не обновляется.Перейдите на react.dev

Состояние и жизненный цикл

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);

Посмотреть на CodePen

В этой главе мы узнаем, как инкапсулировать и обеспечить многократное использование компонента 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);

Посмотреть на CodePen

Проблема в том, что компонент Clock не обновляет себя каждую секунду автоматически. Хотелось бы спрятать логику, управляющую таймером, внутри самого компонента Clock.

В идеале мы бы хотели реализовать Clock таким образом, чтобы компонент сам себя обновлял:

root.render(<Clock />);

Для этого добавим так называемое «состояние» (state) в компонент Clock.

«Состояние» очень похоже на уже знакомые нам пропсы, отличие в том, что состояние контролируется и доступно только конкретному компоненту.

Преобразование функционального компонента в классовый

Давайте преобразуем функциональный компонент Clock в классовый компонент за 5 шагов:

  1. Создаём ES6-класс с таким же именем, указываем React.Component в качестве родительского класса
  2. Добавим в класс пустой метод render()
  3. Перенесём тело функции в метод render()
  4. Заменим props на this.props в теле render()
  5. Удалим оставшееся пустое объявление функции
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Привет, мир!</h1>
        <h2>Сейчас {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Посмотреть на CodePen

Теперь Clock определён как класс, а не функция.

Метод render будет вызываться каждый раз, когда происходит обновление. Так как мы рендерим <Clock /> в один и тот же DOM-контейнер, мы используем единственный экземпляр класса Clock — поэтому мы можем задействовать внутреннее состояние и методы жизненного цикла.

Добавим внутреннее состояние в класс

Переместим date из пропсов в состояние в три этапа:

  1. Заменим this.props.date на this.state.date в методе render():
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Привет, мир!</h1>
        <h2>Сейчас {this.state.date.toLocaleTimeString()}.</h2>      </div>
    );
  }
}
  1. Добавим конструктор класса, в котором укажем начальное состояние в переменной 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>
    )