кодесурса
«Реагировать

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

script1adsense2code
script1adsense3code

В предыдущих уроках мы узнали, что единственный способ обновить пользовательский интерфейс - вызвать метод ReactDOM.render ().

В этом уроке мы рассмотрим концепцию состояния, это мы сделаем, переписав пример тикающих часов из предыдущего урока.

function tick() {
  const element = (
    <div€
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root') );
}
setInterval(tick, 1000);

Мы можем начать с инкапсуляции того, как часы выглядят, разбив вышеперечисленное на биты:

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}
setInterval(tick, 1000);

Тем не менее, он пропускает важнейшее требование: тот факт, что Clock устанавливает таймер и обновляет пользовательский интерфейс каждую секунду, должен быть деталью реализации Clock.

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

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

Чтобы реализовать это, нам нужно добавить «состояние» к компоненту Clock.

Состояние похоже на реквизит, но оно является частным и полностью контролируется компонентом и его изменяемым компонентом. Оно может использоваться только в компонентах класса. Таким образом, мы должны преобразовать вышеуказанный компонент функции Clock в компонент класса.

Преобразование функции в класс

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

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

Часы теперь определены как класс, а не функция.

Метод рендеринга будет вызываться каждый раз, когда происходит обновление, но пока мы рендерим в тот же узел DOM будет использоваться только один экземпляр класса Clock. Это позволяет нам использовать дополнительные функции, такие как локальное состояние и методы жизненного цикла.

Добавление локального состояния в класс

Мы переместим дату из реквизита в состояние в три этапа:

  1. Замените this.props.date на this.state.date в методе render ():
  2. Добавьте конструктор класса, который назначает начальный this.state:
  3. Удалите опору даты из элемента <Clock />:

Окончательный пример кода выглядит так:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  render() {
    return (
      <div€
        <h1>Hello, world!>/h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

Далее, мы заставим Часы настроить собственный таймер и обновлять себя каждую секунду.

Добавление методов жизненного цикла в класс

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

Мы хотим установить таймер всякий раз, когда Clock отображается в DOM в первый раз. Это называется "монтаж" в React.

Мы также хотим очистить этот таймер при удалении DOM, созданного Clock. Это называется «размонтирование» в React.

Мы можем объявить специальные методы в классе компонента для запуска некоторого кода, когда компонент монтируется и демонтируется:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  componentDidMount() {
  }
  componentWillUnmount() {
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Эти методы называются «методы жизненного цикла».

Метод componentDidMount () запускается после визуализации вывода компонента в DOM. Это хорошее место для настройки таймера:

componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

Обратите внимание, как мы сохраняем ID таймера прямо на этом.

Хотя this.props устанавливается самим React, а this.state имеет особое значение, вы можете добавлять дополнительные поля в класс вручную, если вам нужно сохранить что-то, что не участвует в потоке данных (например, идентификатор таймера). ).

Мы разобьем таймер в методе жизненного цикла componentWillUnmount ():

componentWillUnmount() {
    clearInterval(this.timerID);
  }

Наконец, мы реализуем метод tick (), который будет запускаться компонентом Clock каждую секунду.

Он будет использовать this.setState () для планирования обновлений локального состояния компонента:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  tick() {
    this.setState({
      date: new Date()
    });
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

Теперь часы тикают каждую секунду.

Давайте быстро вспомним, что происходит, и порядок вызова методов:

  1. Когда <Clock /> передается в ReactDOM.render (), React вызывает конструктор компонента Clock. Поскольку Clock необходимо отображать текущее время, он инициализирует this.state объектом, включающим текущее время. Мы позже обновим это состояние.
  2. Затем React вызывает метод render () компонента Clock. Вот как React узнает, что должно отображаться на экране. Затем React обновляет DOM, чтобы он соответствовал выводу часов.
  3. Когда вывод Clock вставлен в DOM, React вызывает метод жизненного цикла componentDidMount (). Внутри него компонент Clock просит браузер настроить таймер для вызова метода tick () компонента один раз в секунду.
  4. Каждую секунду браузер вызывает метод tick (). Внутри него компонент Clock планирует обновление пользовательского интерфейса, вызывая setState () с объектом, содержащим текущее время. Благодаря вызову setState () React знает, что состояние изменилось, и снова вызывает метод render (), чтобы узнать, что должно быть на экране. На этот раз this.state.date в методе render () будет другим, поэтому выходные данные рендера будут содержать обновленное время. Реагируйте обновления DOM соответственно.
  5. Если компонент Clock когда-либо удаляется из DOM, React вызывает метод жизненного цикла componentWillUnmount (), поэтому таймер останавливается.

Использование государства правильно

Есть три вещи, которые вы должны знать о setState ().

Не изменяйте состояние напрямую

Например, это не будет повторно визуализировать компонент:

// Wrong
this.state.comment ='Hello';
Instead, use setState():
// Correct
this.setState({comment: 'Hello'});

Единственное место, где вы можете назначить this.state - это конструктор.

Обновления состояния могут быть асинхронными

React может объединять несколько вызовов setState () в одно обновление для повышения производительности.

Поскольку this.props и this.state могут обновляться асинхронно, вы не должны полагаться на их значения для вычисления следующего состояния.

Например, этот код может не обновить счетчик:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

Чтобы исправить это, используйте вторую форму setState (), которая принимает функцию, а не объект. Эта функция получит предыдущее состояние в качестве первого аргумента, а реквизиты во время применения обновления в качестве второго аргумента:

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
We used an arrow function above, but it also works with regular functions:
// Correct
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});

Новый контент: Composer: менеджер зависимостей для PHP , R программирования


script1adsense4code
script1adsense5code
disqus2code
script1adsense6code
script1adsense7code
script1adsense8code
buysellads2code