
- Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
 - Reconciler(协调器)—— 负责找出变化的组件
 - Renderer(渲染器)—— 负责将变化的组件渲染到页面上
 
<React16

挂载阶段
单一组件挂载
constructorcomponentWillMountrendercomponentDidMount
更新阶段
state更新
* 1. shouldComponentUpdate//返回Boolean 类型的值,判断是否需要更新渲染组件,优化 react 应用的主要手段之一// 当返回 false 就不会再向下执行生命周期了// 在这个阶段不可以 setState(),会导致循环调用。* 2. componentWillUpdate//这个生命周期主要提供一个时机能够处理一些在 Dom 发生更新之前的事情,//如获得 Dom 更新前某些元素的坐标、大小等,在这个阶段不可以 setState(),会导致循环调用。************截止至此, this.props 和 this.state 都还未发生更新******* 3. render* 4. componentDidUpdate//在此时已经完成渲染,Dom 已经发生变化,State 已经发生更新,//prevProps、prevState 均为上一个状态的值。
props更新
* 1. componentWillReceiveProps(nextProps,nextState)//生命周期主要为我们提供对 props 发生改变的监听,//如果你需要在 props 发生改变后,相应改变组件的一些 state。// 在这个方法中改变 state 不会二次渲染,而是直接合并 state。* 2. shouldComponentUpdate(nextProps, nextState)//返回Boolean 类型的值,判断是否需要更新渲染组件,优化 react 应用的主要手段之一// 当返回 false 就不会再向下执行生命周期了// 在这个阶段不可以 setState(),会导致循环调用。* 3. componentWillUpdate//这个生命周期主要提供一个时机能够处理一些在 Dom 发生更新之前的事情,//如获得 Dom 更新前某些元素的坐标、大小等,在这个阶段不可以 setState(),会导致循环调用。************截止至此, this.props 和 this.state 都还未发生更新******* 4. render* 5. componentDidUpdate(prevProps, prevState)//在此时已经完成渲染,Dom 已经发生变化,State 已经发生更新,//prevProps、prevState 均为上一个状态的值。
卸载阶段
* componentWillUnmount//此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount 中创建的订阅等。//componentWillUnmount 中不应调用 setState,因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
import React from 'react';import './style.css';class Son extends React.Component {constructor(props) {super(props);console.log('子组件子组件constructor ======>');this.state = {number: 1};}// static getDerivedStateFromProps(props, state) {// console.log('getDerivedStateFromProps =======>');// return props;// }componentWillMount() {console.log('子组件componentWillMount =====>');}componentWillReceiveProps(nextProps, nextState) {//主要提供对 props 发生改变的监听,如果需要在 props 发生改变后,相应改变组件的一些 state。//在这个方法中改变 state 不会二次渲染,而是直接合并 state。console.log('子组件componentWillReceiveProps ===>','nextProps',nextProps,'nextState',nextState);}componentDidMount() {console.log('子组件componentDidMount ======>');}shouldComponentUpdate(nextProps, nextState) {//返回Boolean 类型的值,判断是否需要更新渲染组件,优化 react 应用的主要手段之一// 当返回 false 就不会再向下执行生命周期了// 在这个阶段不可以 setState(),会导致循环调用。console.log('子组件shouldComponentUpdate ====>','nextProps',nextProps,'nextState',nextState,'this.state',this.state);return true;}componentWillUpdate() {console.log('子组件componentWillUpdate =====>', 'this.state', this.state);}componentDidUpdate(prevProps, prevState) {console.log('子组件componentDidUpdate =====>','prevProps',prevProps,'prevState',prevState,'this.state',this.state);}componentWillUnmount() {console.log('子组件componentWillUnmount=====>');}render() {console.log('子组件render ========>');return (<><h1>父组件props{this.props.count}</h1><button onClick={() => this.setState({ count: this.state.number + 1 })}>点击子组件更新状态{this.state.number}</button></>);}}class Parent extends React.Component {constructor(props) {super(props);console.log('constructor ======>');this.state = {count: 1};}// static getDerivedStateFromProps(props, state) {// console.log('getDerivedStateFromProps =======>');// return props;// }componentWillMount() {console.log('componentWillMount =====>');}componentWillReceiveProps(nextProps, nextState) {//主要提供对 props 发生改变的监听,如果需要在 props 发生改变后,相应改变组件的一些 state。//在这个方法中改变 state 不会二次渲染,而是直接合并 state。console.log('componentWillReceiveProps ===>', nextProps, nextState);}componentDidMount() {console.log('componentDidMount ======>');}shouldComponentUpdate(nextProps, nextState) {//返回Boolean 类型的值,判断是否需要更新渲染组件,优化 react 应用的主要手段之一// 当返回 false 就不会再向下执行生命周期了// 在这个阶段不可以 setState(),会导致循环调用。console.log('shouldComponentUpdate ====>',// 'nextProps',// nextProps,// 'nextState',// nextState,'this.state',this.state);return true;}componentWillUpdate() {console.log('componentWillUpdate =====>', 'this.state', this.state.count);}componentDidUpdate(prevProps, prevState) {console.log('componentDidUpdate =====>','prevProps',prevProps,'prevState',prevState,'this.state',this.state);}componentWillUnmount() {console.log('componentWillUnmount=====>');}render() {console.log('render ========>', this.state.count);return (<><h1>生命周期测试</h1><button onClick={() => this.setState({ count: this.state.count + 1 })}>点击更新状态{this.state.count}</button><Son count={this.state.count} /></>);}}export default function App() {return (<div><h1>Hello StackBlitz!</h1><p>Start editing to see some magic happen :)</p><Parent /></div>);}
React16+
https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
组件在挂载dom上的时候,会经历 render和commit阶段
Stack Reconciler重构为Fiber Reconciler后,render阶段的任务可能中断/重新开始,对应的组件在render阶段的生命周期钩子(即componentWillXXX)可能触发多次。这种行为和Reactv15不一致,所以标记为UNSAFE。更详细的解释参照这里(opens new window)为此,React提供了替代的生命周期钩子getSnapshotBeforeUpdate。`
Stack Reconciler重构为Fiber Reconciler后,render阶段的任务可能中断/重新开始,对应的组件在render阶段的生命周期钩子(即componentWillXXX)可能触发多次。这种行为和Reactv15不一致,所以标记为UNSAFE。更详细的解释参照这里(opens new window)为此,React提供了替代的生命周期钩子getSnapshotBeforeUpdate。`
render阶段
没有副作用,可能被中断
包含 constructor 、getDerivedStateFromProps 、shouldComponentUpdate、render 
componentWillRecieveProps/componentWillUpdate/componentWillMount被废弃,由getDerivedStateFromProps代替
commit阶段
有副作用,可以操作dom  
包含componentDidMount、componentDidUpdate、componentWilUnmount
React 16 中删除了如下三个生命周期。
- componentWillMount
 - componentWillReceiveProps
 - componentWillUpdate
 
组件挂载流程
调用ReactDom.render
进入render阶段
采用深度优先遍历算法创建fiber树
进入commit阶段
初始进入页面
constructorgetDerivedStateFromPropsrendercomponentDidMount
状态更新
getSnapshotBeforeUpdate(prevProps, prevState) =>shouldComponentUpdaterendergetSnapshotBeforeUpdate =>// 必须有返回值 返回值作为 componentDidUpdate的第三个参数可以获取componentDidUpdate(prevProps, prevState, valueFromSnapShot) =>

有嵌套情况
import React from 'react';import './style.css';class Son extends React.Component {constructor(props) {super(props);console.log('子组件子组件constructor ======>');this.state = {number: 1};this.sonRef = React.createRef(null);}static getDerivedStateFromProps(props, state) {console.log('子组件getDerivedStateFromProps =======>', props, state);return props;}componentDidMount() {console.log('子组件componentDidMount ======>');}shouldComponentUpdate(nextProps, nextState) {console.log('子组件shouldComponentUpdate ====>','nextProps',nextProps,'nextState',nextState,'this.state',this.state);return true;}getSnapshotBeforeUpdate(prevProps, prevState) {// ...console.log('子组件getSnapshotBeforeUpdate===>', prevProps, prevState);return this.sonRef;}componentDidUpdate(prevProps, prevState, valueFromSnapShot) {console.log('子组件componentDidUpdate =====>','prevProps',prevProps,'prevState',prevState,'valueFromSnapShot',valueFromSnapShot,'this.state',this.state);}componentWillUnmount() {console.log('子组件componentWillUnmount=====>');}render() {console.log('子组件render ========>');return (<div ref={this.sonRef}><h1>父组件props{this.props.count}</h1><button onClick={() => this.setState({ count: this.state.number + 1 })}>点击子组件更新状态{this.state.number}</button></div>);}}class Parent extends React.Component {constructor(props) {super(props);console.log('constructor ======>');this.state = {count: 1};}static getDerivedStateFromProps(props, state) {console.log('getDerivedStateFromProps =======>', props, state);return props;}componentDidMount() {console.log('componentDidMount ======>');}shouldComponentUpdate(nextProps, nextState) {console.log('shouldComponentUpdate ====>',// 'nextProps',// nextProps,// 'nextState',// nextState,'this.state',this.state);return true;}getSnapshotBeforeUpdate(prevProps, prevState) {// ...console.log('getSnapshotBeforeUpdate===>', prevProps, prevState);}componentDidUpdate(prevProps, prevState) {console.log('componentDidUpdate =====>','prevProps',prevProps,'prevState',prevState,'this.state',this.state);}componentWillUnmount() {console.log('componentWillUnmount=====>');}render() {console.log('render ========>', this.state);return (<><h1>生命周期测试</h1><button onClick={() => this.setState({ count: this.state.count + 1 })}>点击更新状态{this.state.count}</button><Son count={this.state.count} /></>);}}export default function App() {return (<div><h1>Hello StackBlitz!</h1><p>Start editing to see some magic happen :)</p><Parent /></div>);}
getDerivedStateFromProps
getDerivedStateFromProps exists for only one purpose. It enables a component to update its internal state as the result of changes in props.
static getDerivedStateFromProps(nextprops, prestate)
- 在 React 16.3.0 版本中:在组件实例化、接收到新的 props 时会被调用
 - 在 React 16.4.0 版本中:在组件实例化、接收到新的 props 、组件状态更新时会被调用
 
注意
- 静态方法。不属于任何实例,内部的this并不指向组件本身,this. 的任何属性和方法都不能用。
 
为什么getDerivedStatefromProps是静态的?
     隔离组件实例访问,不能用this.setState()等一些方法,保持该方法的纯粹,它就是用来定义派生state的,除此之外不能进行任何操作
     保持它是纯函数,不要产生副作用。
- 返回一个对象来更新 state,如果返回 
null则不更新任何内容 - 由上图可以知道,props更新,setState,forceUpdate会触发getDerivedStateFromProps
 
forceUpdate(callback)
默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。
调用 **forceUpdate()** 将致使组件调用 **render()** 方法,此操作会跳过该组件的 **shouldComponentUpdate()**。但其子组件会触发正常的生命周期方法,包括 **shouldComponentUpdate()** 方法。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
替换之前的willX的生命周期,强制用户在mount阶段获取dom
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。
References
https://mp.weixin.qq.com/s/G0xcaQ1KQ9cBgO3yybhDpA
https://github.com/sisterAn/blog/issues/34

