React的生命周期

161 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情

React最新的生命周期是怎么样的

在 React 16 版本中,三个之前的生命周期被标识为废弃,并在 React 17 中计划全部删除它们:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

当它们被删除后,将会只保留三个添加了UNSAVE_前缀的函数版本,作为向下兼容用途。因此我们在新项目中,要尽量避免使用这几个生命周期而使用最新的生命周期函数。

⽬前 React 16.8+ 的⽣命周期分为三个阶段:挂载阶段、更新阶段、卸载阶段。

挂载阶段

constructor :组件的构造函数,它会最先被执⾏,我们通常在构造函数⾥初始化 state 状态对象、或给⾃定义⽅法绑定 this

getDerivedStateFromProps :这是个静态⽅法,当我们接收到新的属性后想要去修改 state 时可以使用

render:这是个只返回需要渲染内容的纯函数,不要包含其它的业务逻辑,可以返回原⽣的 DOM、React 组件、Fragment、Portals、字符串和数字、Boolean 值 和 null 值等内容

componentDidMount :在组件装载后被调⽤,此时可以获取 DOM 节点并操作,对服务器的请求、订阅等操作都可以写在这个地方,但记得要在 componentWillUnmount 中取消订阅,即释放资源

更新阶段

getDerivedStateFromProps :此⽅法在更新个挂载阶段都可能会调⽤

shouldComponentUpdate :该函数有两个参数 nextPropsnextState,表示新的属性和变化之后的状态;它返回⼀个布尔值,true 表示会触发重新渲染,false 则表示不会触发重新渲染,默认返回 true。我们通常利⽤该⽣命周期来优化 React 程序的性能

render :更新阶段也会触发此⽣命周期

getSnapshotBeforeUpdate :该⽅法在 render 之后、在 componentDidUpdate 之前被调⽤,它有两个参数 prevPropsprevState,表示之前的属性和状态,并且该函数有⼀个返回值,返回值会作为第三个参数传给 componentDidUpdate ,如果不想要返回值则返回 null 即可。该⽣命周期必须与 componentDidUpdate 搭配使⽤

componentDidUpdate :该⽅法在 getSnapshotBeforeUpdate ⽅法之后被调⽤,它有三个参数 prevPropsprevStatesnapshot ,表示之前的属性、之前的状态、以及snapshot。第三个参数是 getSnapshotBeforeUpdate 所返回的,如果触发某些回调函数时需要⽤到 DOM 元素的状态,则将对⽐或计算的过程迁移⾄ getSnapshotBeforeUpdate,然后在 componentDidUpdate 中统⼀触发回调或更新状态

卸载阶段

componentWillUnmount :当组件被卸载或销毁时就会被调⽤,我们可以在这个函数⾥去做一些释放资源的操作,如:清除定时器、取消⽹络请求、清理⽆效的 DOM 元素等

在React中网络请求应该放在哪个生命周期中发起

有人认为 React 中的网络异步请求,应该放在 componentWillMount 这个生命周期函数中发起,这样可以提前进⾏异步请求,以避免⽩屏现象。其实这个观点是有问题的。

由于 JavaScript 中异步事件的性质,当进行异步 API 调⽤时,浏览器会在此期间继续执⾏其他⼯作。因此,当 React 渲染⼀个组件时,它并不会等待 componentWillMount 执行完成任何事情,而是继续往前执行并继续做 render ,没有办法 “暂停” 渲染以等待远程数据的返回。

⽽且,在 componentWillMount 中发起请求会存在⼀系列潜在问题:

  • 在用 React 作为服务器渲染(SSR)时,如果在 componentWillMount 中进行数据的获取,则 fetch data 会执⾏两次:⼀次在服务端,⼀次在客户端,这就造成了多余的请求
  • 在 React 16 使用 React Fiber 架构重写后,componentWillMount 可能会在⼀次渲染中被多次调⽤。

⽬前官⽅推荐的是在 componentDidmount 中进行异步请求。

如遇到特殊需求,需要提前进行数据的请求,可考虑采用在 constructor 中进行。

另外,由于在 React 17 之后 componentWillMount 被废弃仅保留 UNSAFE_componentWillMount,所以要慎用该生命周期。