08-React_组件生命周期
Tip:请不要死记生命周期的顺序和作用,要理解 React 将这些生命周期暴露出来给开发者调用是因为开发者有使用这些生命周期的需求,通过这些生命周期,我们可以完成一些事情。
React 旧版生命周期
旧版的 React 的生命周期图如上所示,主要可分为 初始化阶段、挂载阶段、更新阶段、卸载阶段。
初始化阶段
发生在 constructor 中的内容,在 constructor 中进行 state、props 的初始化,在这个阶段修改 state,不会执行更新阶段的生命周期,可以直接对 state 赋值。
挂载阶段
对应的生命周期为:
更新阶段
更新阶段分为由 state 更新引起和 props 更新引起
卸载阶段
对应的生命周期为
* componentWillUnmount
React 新版生命周期
React 16 中删除了如下三个生命周期。
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
官方给出的解释是 react 打算在17版本推出新的异步渲染机制,提出一种可被打断的生命周期,而可以被打断的阶段正是实际 dom 挂载之前的虚拟 dom 构建阶段,因为这三个生命周期可能在一次 render 中被反复调用多次。所以最好的办法是去掉的三个生命周期,为未来的全新异步渲染机制让路。
取代这三个生命周期的是两个新生命周期
- static getDerivedStateFromProps(nextProps,nextState)
这个生命周期主要为我们提供了一个可以在组件实例化 props、state 发生变化后会被调用的函数,用来替代旧的生命周期中的 componentWillMount、ComponentWillReceiveProps。因为是一个静态方法,this 指向不是组件实例。
- getSnapshotBeforeUpdate(prevProps,prevState)
在 render 函数调用之后,实际的 Dom 渲染之前,在这个阶段我们可以拿到上一个状态 Dom 元素的坐标、大小的等相关信息。用于替代旧的生命周期中的 componentWillUpdate。该函数的返回值将会作为 componentDidUpdate 的第三个参数出现。
异步加载数据
学习了组件的生命周期之后,我就就可以来探讨另外一个话题了,就是异步的state, 之前我们演示的demo,数据都是在本地mock。 但是在真实的开发环境中数据都是后端服务提供的接口,我们需要通过 ajax / axios 请求接口获取数据。
ajax / axios 是一个异步操作,这就涉及到这个数据请求的异步任务执行时机的问题了,究竟把异步的数据加载放在哪执行合适,既能正确的请求到数据,又能恰好在组件需要数据进行页面渲染时提供数据。
constructor
constructor设计用来初始化数据用的,而不是数据请求。并且如果请求报错组件无法渲染。
render
render执行异步数据请求可能会导致死循环。因为如果在render中获取数据并setState修改状态,则会再次触发render,然后再次触发异步数据请求,从而陷入死循环。
componentWillMount
问题:服务端渲染时,componentWillMount会执行两次,一次在服务端,一次在客户端。在react16之后,如果开启了异步渲染(fiber),只有componentDidMount生命周期函数确定被执行一次,而componentWillMount、componentwillUpdate、componentWillReceiveProps都可能被执行多次。
最优选择 ComponentDidMount
主要考虑以下两个原因:
- 首次渲染时,在ComponentDidMount之后组件才生成对应的DOM结构,可以通过this.getDOMNode()来进行访问。也就是说,componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以在这个生命周期中执行异步数据请求可以保证数据的加载。
- 在ComponentDidMount中调用setState方法,会触发rerender。官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码。即便开启了react异步渲染(fiber),该生命周期也只会执行一次,不会发生多次调用情况。
安装axios
npm install axios --save
示例代码: