Введение
Начиная с версии React v16.3, хуки жизненного цикла постепенно корректировались, а некоторые функции хуков жизненного цикла были исключены и добавлены соответственно.Эта статья начнется со следующих четырех пунктов:
- Сравнение старых и новых функций жизненного цикла
- Проанализируйте, почему от старых хуков следует отказаться
- Подробно объясните новые сценарии использования жизненного цикла
- Демонстрация примера кода и сводка
Сравнение жизненного цикла старого и нового
Полный жизненный цикл компонента React будет последовательно вызывать следующие хуки:
old lifecycle
устанавливать
- constructor
- componentWillMount
- render
- componentDidMount
возобновить
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
удалить
- componentWillUnmount
new lifecycle
- устанавливать
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
- возобновить
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
- удалить
- componentWillUnmount
Из сравнения приведенного выше жизненного цикла нетрудно увидеть, что React был заброшен, начиная с версии 16.3.componentWillMount
componentWillReceiveProps
componentWillUpdate
Три функции крючка
Проанализируйте причины отказа
У Facebook ушло более двух лет на то, чтобы придумать React Fiber, потому что в версии v15 процесс обновления синхронный, и часто основной поток занят надолго, что вызовет проблемы с производительностью страницы
а такжеМеханизм React Fiber:Используйте браузерrequestIdleCallback
Прерываемые задачи разделены на осколки, а время выполнения каждого маленького кусочка очень короткое, так что единственный поток не монополизирован.
Для получения более подробной информации, пожалуйста, нажмите на ссылку нижеМорган босс
Итак, какое влияние React Fiber оказывает на жизненный цикл?
Потому что Реактивное волокноReconciliation
Этот процесс может быть приостановлен, а затем продолжать выполняться, поэтому перехватчики жизненного цикла перед монтированием и обновлением могут не выполняться или выполняться несколько раз;
React в настоящее время предоставляет псевдонимы для этих хуков жизненного цикла, а именно:
- UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate
React17 будет предоставлять только псевдонимы, и цель использования псевдонима — вызвать у вас отвращение и помешать вам его использовать.
Подробно объясните новый жизненный цикл
Функции жизненного цикла каждого этапа
constructor()
constructor()
Вызывается перед монтированием компонентов React, должен вызываться перед другими операторами при реализации конструкторов для подклассов React.Component.super()
Роль super: наследовать this объект родительского класса дочернему классу (Справочник MDN)
Обычно конструкторы React используются только в следующих двух случаях:
- Инициализировать внутреннее состояние функции
- дляобработчик событияэкземпляр привязки
Если не инициализирован
state
или без привязки метода вам не нужно писатьconstructor()
, просто установитеthis.state
Только что
не может быть в
constructor()
Внутри вызова конструктораthis.setState()
, потому что в первый разrender()
Еще не выполнено, что означает, что узел DOM не был смонтирован
static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps()
вызовrender
Вызывается перед методом, будет вызываться во время инициализации и последующих обновлений
Возвращаемое значение: возвращает объект для обновления.
state
, если вернутьсяnull
тогда ничего не обновляй
Параметры: первый параметр должен быть обновлен
props
, второй параметр — значение предыдущего состоянияstate
, можно сравнитьprops
а такжеstate
добавить некоторые ограничения для предотвращения бесполезных обновлений состояния
Уведомление:
getDerivedStateFromProps
Это статическая функция, и она не может использовать это, то есть может выполнять только некоторые операции без побочных эффектов.
А почему? пожалуйста, переместитеМорган босс
render()
render()
Метод — это единственный метод, который должен быть реализован в компоненте класса, который используется для рендеринга dom,render()
метод должен возвращать reactDOM
Примечание: не
render
вsetState
, иначе это вызовет бесконечный цикл и приведет к повреждению памяти.
componentDidMount()
componentDidMount()
Сразу после монтирования компонента (после вставки в DOM-дерево)componentDidMount()
Это хорошее время для отправки сетевых запросов, включения методов прослушивания событий и их можно вызывать непосредственно в этой функции ловушки.setState()
shouldComponentUpdate(nextProps, nextState)
shouldComponentUpdate()
Вызывается перед обновлением компонента, вы можете контролировать, обновляется ли компонент, обновляется ли компонент, когда он возвращает true, и не обновляется, когда он возвращает false
Содержит два параметра, первый — это значение реквизита, которое необходимо обновить, а второй — значение состояния, которое необходимо обновить.Вы можете сравнить и добавить некоторые ограничения на основе реквизита или состояния до и после обновления, чтобы решить, следует ли обновлять и выполнять оптимизация производительности.
не рекомендуется в
shouldComponentUpdate()
подробное сравнение или использованиеJSON.stringify()
. Это очень неэффективно и снижает производительность.
не хочу
shouldComponentUpdate
Вызовите setState() в , иначе это вызовет бесконечный цикл вызова обновления и рендеринга, пока память браузера не выйдет из строя.
можно использовать встроенный
PureComponent
замена компонентов
getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate()
Вызывается перед фиксацией самого последнего вывода рендеринга. То есть после рендера, когда компонент вот-вот будет смонтирован.
Это позволяет компоненту собирать некоторую информацию (например, положение прокрутки) до фактического обновления DOM, любое значение, возвращаемое этим жизненным циклом, передается в качестве параметра в
componentDidUpdate()
. Возвращает null, если не нужно передавать значение
componentDidUpdate(prevProps, prevState, snapshot)
componentDidUpdate()
будет вызываться сразу после обновления. Первый рендер не будет выполнен
Содержит три параметра, первый — это последнее значение реквизита. Второе — это последнее значение состояния. Если компонент реализует
getSnapshotBeforeUpdate()
Жизненный цикл (обычно не используется), третий — передача параметра «моментального снимка».
Вы можете сравнить реквизиты до и после, чтобы ограничить выполнение условного оператора.
setState()
, иначе это приведет к бесконечному циклу
componentWillUnmount()
componentWillUnmount()
Вызывается, когда компонент собирается быть размонтированным или уничтоженным.
Этот жизненный цикл являетсяотменить сетевой запрос, Удалитьпрослушать событие,Очистить элементы DOM,таймер очисткиОжидание подходящего времени для работы
порядок выполнения жизненного цикла
при создании
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
При обновлении
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
при удалении
- componentWillUnmount()
Пример дисплея
Реагирующая версия следующего кода — 16.4.0, которая будет изменена в соответствии с реквизитами родительского и дочернего компонентов, родительский компонент выгружается, повторно монтирует дочерний компонент, а дочерний компонент меняет свое собственное состояние. объясняется жизненный цикл.
Отображение кода компонента
Родительский компонент: Parent.js
import React, { Component } from 'react';
import { Button } from 'antd';
import Child from './child';
const parentStyle = {
padding: 40,
margin: 20,
backgroundColor: 'LightCyan',
};
const NAME = 'Parent 组件:';
export default class Parent extends Component {
constructor() {
super();
console.log(NAME, 'constructor');
this.state = {
count: 0,
mountChild: true,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
/**
* 修改传给子组件属性 count 的方法
*/
changeNum = () => {
let { count } = this.state;
this.setState({
count: ++count,
});
};
/**
* 切换子组件挂载和卸载的方法
*/
toggleMountChild = () => {
const { mountChild } = this.state;
this.setState({
mountChild: !mountChild,
});
};
render() {
console.log(NAME, 'render');
const { count, mountChild } = this.state;
return (
<div style={parentStyle}>
<div>
<h3>父组件</h3>
<Button onClick={this.changeNum}>改变传给子组件的属性 count</Button>
<br />
<br />
<Button onClick={this.toggleMountChild}>卸载 / 挂载子组件</Button>
</div>
{mountChild ? <Child count={count} /> : null}
</div>
);
}
}
Дочерний компонент: Child.js
import React, { Component } from 'react';
import { Button } from 'antd';
const childStyle = {
padding: 20,
margin: 20,
backgroundColor: 'LightSkyBlue',
};
const NAME = 'Child 组件:';
export default class Child extends Component {
constructor() {
super();
console.log(NAME, 'constructor');
this.state = {
counter: 0,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
changeCounter = () => {
let { counter } = this.state;
this.setState({
counter: ++counter,
});
};
render() {
console.log(NAME, 'render');
const { count } = this.props;
const { counter } = this.state;
return (
<div style={childStyle}>
<h3>子组件</h3>
<p>父组件传过来的属性 count : {count}</p>
<p>子组件自身状态 counter : {counter}</p>
<Button onClick={this.changeCounter}>改变自身状态 counter</Button>
</div>
);
}
}
дисплей интерфейса
Исследуйте порядок выполнения жизненного цикла по времени изменения состояния пяти компонентов.
1. Инициализация родительского и дочернего компонентов
Когда родительский и дочерний компоненты визуализируются и загружаются в первый раз:
Последовательность печати для консоли:
- Родительский компонент: конструктор()
- Родительский компонент: getDerivedStateFromProps()
- Родительский компонент: рендер()
- Дочерний компонент: конструктор()
- Дочерний компонент: getDerivedStateFromProps()
- Дочерний компонент: рендер()
- Дочерний компонент: componentDidMount()
- Родительский компонент: componentDidMount()
Во-вторых, дочерний компонент изменяет свое собственное состояние.
Нажмите кнопку субкомпонента [Изменить собственный счетчик состояния], значение его [собственного счетчика состояния] будет равно +1, а порядок печати консоли будет следующим:
-
Дочерний компонент: getDerivedStateFromProps()
-
Дочерний компонент: shouldComponentUpdate()
-
Дочерний компонент: рендер()
-
Дочерний компонент: getSnapshotBeforeUpdate()
-
Дочерний компонент: componentDidUpdate()
3. Измените реквизиты, переданные в дочерний компонент в родительском компоненте.
Нажмите кнопку [Изменить количество атрибутов, переданных дочернему компоненту] в родительском компоненте, значение [количество атрибутов, переданных из родительского компонента] в интерфейсе будет + 1, а порядок печати консоли будет следующим:
-
Родительский компонент: getDerivedStateFromProps()
-
Родительский компонент: shouldComponentUpdate()
-
Родительский компонент: рендер()
-
Дочерний компонент: getDerivedStateFromProps()
-
Дочерний компонент: shouldComponentUpdate()
-
Дочерний компонент: рендер()
-
Дочерний компонент: getSnapshotBeforeUpdate()
-
Родительский компонент: getSnapshotBeforeUpdate()
-
Дочерний компонент: componentDidUpdate()
-
Родительский компонент: componentDidUpdate()
4. Удалить подкомпоненты
Нажмите кнопку [Удалить/смонтировать дочерний компонент] в родительском компоненте, дочерний компонент исчезнет из интерфейса, а последовательность печати консоли будет следующей:
-
Родительский компонент: getDerivedStateFromProps()
-
Родительский компонент: shouldComponentUpdate()
-
Родительский компонент: рендер()
-
Родительский компонент: getSnapshotBeforeUpdate()
-
Дочерний компонент: componentWillUnmount()
-
Родительский компонент: componentDidUpdate()
5. Перемонтируйте подкомпоненты
Нажмите кнопку [Удалить/смонтировать дочерний компонент] в родительском компоненте еще раз, дочерний компонент будет повторно отображен в интерфейсе, а порядок печати консоли будет следующим:
-
Родительский компонент: getDerivedStateFromProps()
-
Родительский компонент: shouldComponentUpdate()
-
Родительский компонент: рендер()
-
Дочерний компонент: конструктор()
-
Дочерний компонент: getDerivedStateFromProps()
-
Дочерний компонент: рендер()
-
Родительский компонент: getSnapshotBeforeUpdate()
-
Дочерний компонент: componentDidMount()
-
Родительский компонент: componentDidUpdate()
Сводка порядка выполнения жизненного цикла родительско-дочернего компонента:
-
При изменении состояния дочернего компонента родительский компонент не будет обновляться без каких-либо побочных эффектов на родительский компонент, то есть жизненный цикл родительского компонента не будет запущен
-
Когда состояние родительского компонента изменяется (включая монтирование и выгрузку дочернего компонента), это запускает соответствующий жизненный цикл и обновление дочернего компонента.
-
render
так же какrender
предыдущий жизненный цикл, родительский компонент выполняется первым -
render
так же какrender
В последующем цикле объявления дочерний компонент выполняется первым и выполняется поочередно с родительским компонентом.
При удалении дочернего компонента сохраняется только его собственный
componentWillUnmount
Жизненный цикл, не запускает другие жизненные циклыЭто мое резюме, основанное на том, что я узнал.Если есть какие-либо недостатки, вы можете оставить сообщение для меня, чтобы исправить. Наконец, я надеюсь, что каждый может поставить больше лайков + подписаться, ваше признание - движущая сила для меня, чтобы двигаться вперед!
-
пример кода
Для тех, кому нужно проверить, пожалуйста, нажмитерасположение кода