Жизненный цикл

1. Жизненный цикл компонента

Существует несколько стадий жизненного цикла, каждый из которых вызывает для компонента методы наследуемые от React.Component. Мы можем переопределить их поведение добавив необходимый функционал, в рамках установленных правил.

2. Стадия монтирования

Следующие методы вызываются когда создается экземпляр компонента и добавляется в DOM.

constructor() {}

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

  • Инициализирует начальное состояние компонента

  • Привязывает контекст в методах

  • Нельзя вызывать setState()

  • В большинстве случаев явное указание конструтора излишне

static getDerivedStateFromProps(nextProps, prevState) {}
  • Вызывается перед render(), при монтировании и перед всеми последующими вызовами render, тоесть после обновления state или props.

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

  • Должен вернуть объект, которым будет обновлено состояние, или null если ничего обновлять не нужно.

  • Нут доступа к this

render() {}
  • Позволяет декларативно описать интерфейс

  • Возвращает результат JSX-выражений, поддерево Virtual DOM

  • Нельзя вызывать setState()

componentDidMount() {}
  • Вызывается сразу после монтирования в DOM

  • Делаем HTTP-запросы, вешаем кастомные слушатели событий и делаем операции с DOM

  • Вызов setState() в этом методе, вызовет ре-рендер - это нормально

3. Стадия обновления

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

shouldComponentUpdate(nextProps, nextState) {}
  • Не вызывается при инициализации компонента

  • Вызывается перед ре-рендером уже существующего компонента

  • Необходим исключительно для оптимизации процесса рендера

  • По умолчанию render происходит каждый раз при новых props или state

  • Позволяет сравнить текущие и предыдущие state и props, вернув true или false указывая React есть ли необходимость обновлять компонент

  • Если вернет false то не произойдет render() и componentDidUpdate()

  • Нельзя вызывать setState()

  • Использовать необходимо очень аккуратно, только после замеров производительности, в противном случае может привести к обратному эффекту

  • Возможно стоит заменить на React.PureComponent, который будет делать поверхностное сравнение props. Но только после замеров производительности

getSnapshotBeforeUpdate(prevProps, prevState) {}
  • Вызывается перед тем, как все изменения готовы к добавлению в DOM

  • Можно использовать для получения DOM-значений перед обновлением, к примеру текущую позицию скрола

  • То что вернет этот метод, будет передано как третий параметр в componentDidUpdate()

componentDidUpdate(prevProps, prevState, snapshot) {}
  • Вызывается сразу после обновления компонента

  • Не вызывается при первоначальном рендере компонента

  • Можно вызывать setState(), обязательно обернув его в условие проверки изменения предыдущих и следующих props и state, чтобы не возник бесконечный цикл.

  • Можно делать HTTP-запросы

  • Можно передавать сторонним библиотекам новые данные

  • Если в компоненте есть getSnapshotBeforeUpdate(), то значение возвращаемое им будет передано третим аргументом snapshot, в противном случае его значением будет undefined

4. Стадия размонтирования

В какой-то момент компоненты будут удалены из DOM. При этом вызывается следующий метод.

componentWillUnmount() {}
  • Вызывается перед размонтированием и удалением элемента из DOM

  • Отлично подходим для уборки за собой: слушатели, таймеры, HTTP-запросы. В противном случае будут утечки памяти

  • Вызывать setState() нет смысла, компонент никогда не перерендерится

5. Обработка ошибок рендера

React очень любит класть все приложение при любой ошибке. Метод componentDidCatch срабатывает при ошибке в дочернем компоненте и позволяет родительским компонентам отлавливать ошибки в детях, отображая запасной интерфейс. В результате, при ошибке, интерфейс не падает.

componentDidCatch(error, info) {}
  • Используется для контроля ошибок

  • Ловит ошибки только в детях, но не в самом родителе

  • error - результат toString() объекта ошибки

  • info - объект описывающий stack trace

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  componentDidCatch(error, info) {
    // Если метод был вызван значит есть ошибка!
    // Устанавливаем состояние
    this.setState({ hasError: true });
    // Также можно отправить отчет об ошибке вашему аналитическому сервису
    // logErrorToMyService(error, info);
  }

  render() {
    // Если есть ошибка...
    if (this.state.hasError) {
      // Рендерим fallback UI
      return <h1>Something went wrong, please try again later :(</h1>;
    }

    // Если все ок, рендерим детей
    return this.props.children;
  }
}

6. Дополнительные материалы

Last updated

Was this helpful?