Життєвий цикл
Існує кілька стадій життєвого циклу – монтування, оновлення та розмонтування.
Під час кожної з них у компонента-класу викликаються методи, що наслідуються від
React.Component. Ми можемо перевизначити їхню поведінку, додавши необхідний
функціонал в рамках встановлених правил.
Всього є сім методів життєвого циклу, якщо не рахувати render і constructor.
На практиці, в більшості повсякденних завдань використовують три:
componentDidMount, componentDidUpdate і componentWillUnmount.
Посилання на оригінальну сторінку діаграми
Стадія монтування
Наступні методи викликаються у такому порядку, коли створюється екземпляр компонента і додається в 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()у цьому методі викличе повторний рендер – це нормально
Стадія оновлення
Оновлення може бути викликано зміною 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-значень перед оновленням, наприклад, поточну позицію скрола або розмір елемента до оновлення
- Те, що поверне цей метод, буде передане як третій параметр
snapshotвcomponentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot) {}
- Викликається відразу після оновлення компонента в DOM
- Не викликається при початковому рендері компонента
- Можна викликати
setState(), обов'язково обгорнувши його в умову перевірки зміни попередніх і наступнихpropsабоstate, щоб не виник нескінченний цикл ререндера (вкладка зависне або впаде). - Можна робити HTTP-запити
- Якщо в компоненті є
getSnapshotBeforeUpdate(), то значення, що повертається їм, буде передане третім аргументомsnapshot, в іншому випадку його значенням будеundefined
Стадія розмонтування
У якийсь момент компонент буде видалений з DOM. При цьому викликається наступний метод.
componentWillUnmount() {}
- Викликається перед розмонтуванням та видаленням елемента з DOM
- Добре підходить для прибирання за собою: слухачі, таймери, HTTP-запити. В іншому випадку будуть витоки пам'яті
- Викликати
setState()немає сенсу, компонент ніколи не перерендериться
Обробка помилок рендеру
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;
}
}