React新生命周期

react官方打算在未来提出一种实现异步渲染的方法以提高性能,主要的特点就是在渲染完成之前可以被中断,中断之后不会继续执行生命周期,而是重头开始执行生命周期。

所以官方决定,从v17开始删除以下三个生命周期钩子:

componentWillMount
componentWillReceiveProps
componentWillUpdate

作为补偿,新增两个新的生命周期钩子

static getDerivedStateFromProps
getSnapshotBeforeUpdate

新生命周期钩子

static getDerivedStateFromProps

用法:

  • 触发时间:
    • 实例创建之后
    • 每次获取到新的props或者新的state(即setState)之后
  • 参数
    • nextProps
    • nextState
  • 返回值
    • 如果返回一个Object,则相当于进行一次setState操作(注意,这里返回对象虽然改变了state,但不会再次触发此函数)
    • 如果为null,则不更新state
    • 如果无返回值(即默认return undefined),报错
    • 如果返回一个基本类型值(如return 666;),则与返回null无区别

这里需要注意的是:

  • getDerivedStateFromProps是一个静态方法,this为undefined,不指向实例,所以也拿不到实例的属性和方法。至于为什么要将此方法设计为静态方法,官方文档解释:以后的组件将进行异步渲染,防止实例属性的被不安全访问,编写出异步兼容的代码
  • 此方法不提供一个prevProps的参数,官方解释为,首次执行此方法,prevProps是null,那么每次调用此方法都要判断一次,很耗性能。其次,如果大家以后都习惯没有prevProps的日子,那么react就不保存prevProps的引用了,节省内存,提高性能(心里一万匹***奔腾而过)
  • 如果要访问prevProps,只能将一些props的属性记录到state里面去了
  • 不能同上述提到即将要被删除掉的三个生命周期钩子同时使用

getSnapshotBeforeUpdate

用法:

  • 触发时间:update发生的时候,在render之后,在组件dom渲染之前
  • 参数:prevProps, prevState(prevState为上一次更新中getDerivedStateFromProps方法执行后state的值)
  • 返回值可以为任意值,且返回值将作为componentDidUpdate的第三个参数

这里需要注意的是:

  • 与componentDidUpdate成对使用,否则会报错
  • 不能同上述提到即将要被删除掉的三个生命周期钩子同时使用

为什么要删除三个生命周期钩子

其实官方解释是,很多react用户(包括我)都存在错误的使用这三个生命周期钩子的行为,导致以后异步渲染时,会导致极大的性能损耗,所以强制将这三个钩子删除掉(v17版本之后,现在还是可以使用的)。那接下来看看在这三个生命周期到底存在什么错误的用法:

componentWillMount

错误做法:

  • 天真地认为在这里请求异步数据,首屏渲染就会有数据了
  • 在此添加事件监听方法
  • 在此初始化state(根据props进行setState)

缺点:

  • 在此发起异步数据请求之后,会立刻调用render方法,那么首屏渲染还是没有数据
  • 服务器渲染,不会调用componentWillUnmount方法,那么在此钩子里面添加的事件监听方法就无法被浏览器移除,导致内存泄露;同时,在此钩子请求异步数据,也无法首屏渲染数据(原因同上一点),返回到前端还是空白页面。
  • 上面提到多,渲染可被打断,如果被打断,那么就可能会多次调用此钩子,导致多次请求数据,消耗性能

优化

  • 在constructor里面进行state的初始化
  • 在componentDidMount里面请求异步数据和添加事件监听方法(因为此时能够确保componentWillUnmount钩子一定会执行,就可在这个地方进行销毁事件监听器,回收内存)
  • 解决服务端渲染的问题,可以查阅一下react的同构直出的方法

componentWillReceiveProps

错误做法:

  • 根据前后props数据的对比更新state
  • 根据前后props数据的对比请求异步数据

缺点:

  • 更新state方式不优雅
  • 职能不专,同时进行setState和获取异步数据等会触发新一轮组件更新的操作
  • 渲染可被中断,会多次请求数据

优化:

  • 使用getDerivedStateFromProps返回值来更新state
  • 在componentDidUpdate获取数据

componentWillUpdate

错误做法:

  • 根据新的state发起异步数据请求
  • 在此进行外部函数调用(如nextProps.someMethod())
  • 记录更新前一些节点的属性(这个做法没错,只是现在有更好的方式)

缺点:

  • 异步数据和外部函数调用请求的缺点同前面两个钩子的一样
  • 记录的信息如果放在state中,需要额外的判断(会进行两次更新)

优化:

  • 在componentDidUpdate 在此处数据请求和外部函数调用
  • 在getSnapshotBeforeUpdate记录当前节点信息,记录的信息通过返回值传递给componentDidUpdate作为第三个参数(省内存,仅一次更新)

总结

新生命周期的思想就是:确保渲染完成之前不做任何会引发重新渲染的操作

新生命周期流程图(来自react官网)

最后,附上react rfcs文档地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值