总结
- 当props或者state被修改时,就会引发组件的更新过程
- 只有render和shouldComponentUpdate需要返回结果
- 不建议在 getDefaultProps、getInitialState、shouldComponentUpdate、componentWillUpdate、render 和 componentWillUnmount 中调用 setState,特别注意:不能在 shouldComponentUpdate 和 componentWillUpdate中调用 setState,会导致循环调用。
- setState 会先进行 _pendingState 更新队列的合并操作,不会立刻 reRender,因此是异步操作,且通过判断状态(MOUNTING、RECEIVE_PROPS)来控制 reRender 的时机
挂载阶段
getDefaultProps
- object getDefaultProps()
- 执行过一次后,被创建的类会有缓存,映射的值会存在this.props,前提是这个prop不是父组件指定的
- 这个方法在对象被创建之前执行,因此不能在方法内调用this.props
注意任何getDefaultProps()返回的对象在实例中共享,不是复制
getInitialState
object getInitialState()
-
componentWillMount
void componentWillMount()
- 执行一次,在初始化render之前执行
在这个方法内调用setState,render()知道state发生变化,并且只执行一次
render
ReactElement render()
- 决定了组件该渲染什么
- 调用render()
- 调用render()方法时,首先检查this.props和this.state返回一个子元素,子元素可以是DOM组件或者其他自定义复合控件的虚拟实现
- 如果不想渲染可以返回null或者false,这种场景下,react渲染一个
<noscript>
标签 - 当返回null或者false时,ReactDOM.findDOMNode(this)返回null
- 不要在这个方法里初始化组件的state,每次执行时返回相同的值
这个方法不会读写DOM或者与服务器交互,如果必须如服务器交互,在componentDidMount()方法中实现或者其他生命周期的方法中实现,保持render()方法纯净使得服务器更准确,组件更简单
componentDidMount
void componentDidMount()
- 在初始化render之后只执行一次
- 从这个函数开始,可以访问任何组件,可以和 js 其他框架交互,可以设置计时 setTimeout 或者 setInterval,或者发起网络请求
- componentDidMount()方法中的子组件在父组件之前执行
更新阶段
componentWillReceiveProps(删除)
从这个生命周期开始触发组件的更新过程
- void componentWillReceiveProps(object nextProps)
- 一个组件要从父组件接受参数,只要父组件的render函数被重新调用,在render函数里面渲染的子组件就会经历更新过程,不管父传给子的props有没有改变
- 这个函数适合根据新的props值(也就是参数nextProps)来计算出是不是要更新内部状态state
- 这个生命周期有必要把传入的参数nextProps和this.props作必要的对比,只有两者有变化时才有必要通过调用this.setState()来更新组件的状态
- 旧的属性还是可以通过this.props来获取,
- 这里调用更新状态是安全的,并不会触发额外的render调用
static getDerivedStateFromProps(nextProps, prevState)
- 无论是 Mounting 还是 Updating,也无论是因为什么引起的 Updating,全部都会被调用
- 每次接收新的 props 之后都会返回一个对象作为新的 state,返回 null 则说明不需要更新state
- 注意 getDerivedStateFromProps 是一个 static 方法,意味着拿不到实例的 this
shouldComponentUpdate
- boolean shouldComponentUpdate(object nextProps, object nextState)
- 决定了一个组件什么时候不需要渲染
- 在第二个render之前执行
- 父组件render和this.setState()都会经过的生命周期函数
- nextProps: 父组件render时是否渲染
- nextState:调用this.setState()时是否渲染
- 当组件比较多时,使用这个方法能有效提高应用性能
- 返回true, 则会执行render()方法
- 返回false, 不会执行render()方法,componentWillUpdate和componentDidUpdate方法也不会被调用
- 默认情况下,shouldComponentUpdate方法返回true防止state快速变化时的问题,
- 但是如果·state不变,props只读,可以直接覆盖shouldComponentUpdate用于比较props和state的变化,决定UI是否更新
getSnapshotBeforeUpdate(prevProps, prevState)
- 被调用于 render 之后,可以读取但无法使用 DOM 的时候。
- 它使您的组件可以在可能更改之前从 DOM 捕获一些信息(例如滚动位置)。
- 此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。
- 该函数与 componentDidUpdate 一起使用可以取代 componentWillUpdate 的所有功能
componentWillUpdate(删除)
- void componentWillUpdate(object nextProps, object nextState)
- 当props和state发生变化时执行
- 在这个函数里面,就不能使用this.setState来修改状态
这个函数调用之后,就会把nextProps和nextState分别设置到this.props和this.state中。紧接着这个函数,就会调用render()来更新界面了
componentDidUpdate
void componentDidUpdate(object prevProps, object prevState)
- 组件更新结束之后执行,在初始化render时不执行
卸载阶段
componentWillUnmount
- void componentWillUnmount()
- 当组件要被从界面上移除时调用
- 在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等
错误捕获
componentDidCatch(err, info)
- 组件内的异常有可能会影响到 React 的内部状态,进而导致下一轮渲染时出现未知错误。
- 这些组件内的异常往往也是由应用代码本身抛出,在之前版本的 React 更多的是交托给了开发者处理,而没有提供较好地组件内优雅处理这些异常的方式。
- 在 React 16.x 版本中,引入了所谓 Error Boundary 的概念,从而保证了发生在 UI 层的错误不会连锁导致整个应用程序崩溃;未被任何异常边界捕获的异常可能会导致整个 React 组件树被卸载。
- 所谓的异常边界即指某个能够捕获它的子元素(包括嵌套子元素等)抛出的异常,并且根据用户配置进行优雅降级地显示而不是导致整个组件树崩溃。
异常边界能够捕获渲染函数、生命周期回调以及整个组件树的构造函数中抛出的异常。
生命周期阶段
首次渲染
- willMount
- render
- didMount
- props更新时
- receiveProps
- shouldUpdate
- willUpdate
- render
- didUpdate
- state更新时
- shouldUpdate
- willUpdate
- render
- didUpdate
- 卸载
- 去掉了3个方法
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
- 增加了2个方法
- static getDerivedStateFromProps(nextProps, prevState)
- getSnapshotBeforeUpdate(prevProps, prevState)
更改了1个方法,增加了第3个参数
UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate