生命周期
React 组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用
我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作
生命周期流程(旧)
简述
React 生命周期可以分成三个阶段:
- 挂载阶段:组件状态数据的初始化及初始化渲染
- 运行阶段:和用户交互,改变状态并重绘(最长阶段)
- 卸载阶段:组件使用完毕后,或者不需要存在于页面中,那么将组件移除,执行销毁(需注意内存泄漏问题)
以类式组件的创建流程为例:
- 执行
ReactDOM.render
- 解析组件标签,找到组件
- 发现组件是类定义组件,new 该类实例,通过该实例调用原型上的 render 方法
- 将 render 返回的虚拟 DOM 转换为真实 DOM,随后呈现在页面中
render 调用的时机:初始化渲染、状态更新之后
旧生命周期流程图

流程分析
初始化阶段:ReactDOM.render()
触发初次渲染
- constructor
- componentWillMount
- render
- componentDidMount
componentDidMount 为常用钩子函数,一般在这个钩子中做一些初始化的事,如:开启定时器、发送网络请求、订阅消息等
更新阶段:组件setState()
或父组件 render 触发
- componentWillReceiveProps(初始化时不触发,父组件没有更新不触发)
- shouldComponentUpdate(setState 时触发)
- componentWillUpdate(forceUpdate)
- render
- componentDidUpdate
卸载阶段:由ReactDOM.unmountComponentAtNode()
触发
- componentWillUnmount
componentWillUnmount 为常用钩子函数,一般在这个钩子中做一些收尾的事,如:关闭定时器、取消订阅消息
生命周期流程(新)
简述
新生命周期不是对旧生命周期的颠覆,而是合理地优化更新
新的生命周期没有 componentWillMount
componentWillReceiveProps
componentWillUpdate
钩子函数,以避免异步渲染可能存在的问题
上述三个旧版本生命周期函数在 18.0.X 版本需要在函数名前面添加 UNSAFE_ (UNSAFE_componentWillMount() {}
)才能工作。
新生命周期增加了一些新的钩子函数
新生命周期流程图

流程分析
初始化阶段:ReactDOM.render()
触发初次渲染
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
componentDidMount 仍是常用钩子函数
更新阶段:组件setState()
或父组件 render 触发
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
卸载阶段:由ReactDOM.unmountComponentAtNode()
触发
- componentWillUnmount
componentWillUnmount 仍是常用钩子函数
父子附件渲染顺序
组件渲染的顺序依赖于深度优先原则
父组件第一次渲染:
父 willMount -> 父 render [ 子 willMount -> 子 render -> 子 didMount ] -> 父 didMount
父组件更新:
父 getDerivedStateFromProps -> 父 shouldUpdate -> 父 render -> [ 子父 getDerivedStateFromProps -> 子 shouldUpdate -> 子 render -> 子 didUpdate ] -> 父 didUpdate
特殊情况:我们可以在子组件内部优化处理,验证传递的属性值有没有变化,如果没有变化则禁止更新(memo)
父组件释放:
父 willUnMount -> 父释放中 -> [ 子 willUnMount -> 子释放 ] -> 父释放
重要的钩子
render:初始化渲染或更新渲染调用
componentDidMount:开启监听, 发送 ajax 请求
componentWillUnmount:做一些收尾工作, 如: 清理定时器