一、React 15 版本的生命周期
-
挂载阶段
-
constructor构造函数 -
componetWillMount组件初始化渲染前调用 -
render组件渲染 -
componentDidMount组件挂载到DOM后调用
-
-
更新阶段
componentWillReceiveProps组件将要接收新props前调用shouldComponentUpdate组件是否需要更新componentWillUpdate组件更新前调用render组件渲染componentDidUpdate组件更新后调用
-
卸载阶段
componentWillUnmount组件卸载前调用
二、16版本的生命周期
-
挂载阶段
-
constructor构造函数,如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。 -
static getDerivedStateFromProps(props, state)会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。 -
render -
componentDidMount组件挂载到DOM后调用。在这里可以直接调用setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。从而保证了即使在render()两次调用的情况下,用户也不会看到中间状态。但它会导致性能问题,所以要谨慎使用。
-
-
更新
static getDerivedStateFromPropsshouldComponentUpdaterendergetSnapShotBeforeUpdate在最近一次渲染输出(提交到 DOM 节点)之前调用。它使组件能在发生更改之前从 DOM 捕获一些信息(例如,滚动位置)。它的任何返回值将作为参数传递给componentDidUpdate。componentDidUpdate组件更新后调用,首次渲染不会执行此方法。在这里直接调用setState()时,必须将setState()包裹在一个条件语句里,否则会导致死循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。
-
卸载
componentWillUnmount这里不应调用setState(),因为组件不会重新渲染。
-
错误处理
static getDerivedStateFromError在后代组件抛出错误后被调用,将抛出的错误作为参数,并返回一个值以更新 state。componentDidCatch
三、为什么要移除componentWillMount、componentWillReceivepPops和componentWillUpdate?
componentWillMount:异步渲染机制可能会导致单个组件实例可以多次调用该方法。很多开发着目前会将事件绑定、异步请求等写在componentWillMount中,一旦异步渲染时componentWillMount被多次调用,将会导致:- 进行重复的事件监听,无法正常取消重复的 Listener,更有可能导致内存泄漏;
- 发出重复的异步网络请求,导致 IO 资源被浪费;
- 在服务端渲染时,
componentWillMount会被调用,但是会因忽略异步获取的数据导致 IO 资源被浪费。
- 大多数开发者使用
componentWillUpdate的场景是配合componentDidUpdate,分别获取 rerender 前后的视图状态,进行必要的处理。但随着 suspense、time slicing、异步渲染等机制的到来,render 过程可以被分割成多次完成,还可以被暂停甚至回溯,这导致**componentWillUpdate和componentDidUpdate执行前后可能会间隔很长时间**,足够使用户进行交互操作更改当前组件的状态,这样可能会导致难以追踪的 bug。
参考:
- React 高频面试题梳理,看看面试怎么答?(上): mp.weixin.qq.com/s/3jmJgZFkt…
- 【React官网】React.Component: zh-hans.reactjs.org/docs/react-…
- 【IMWeb】谈谈新的 React 新的生命周期钩子: imweb.io/topic/5b8ca…