浅谈React中的生命周期getDerivedStateFromProps以及getSnapshotBeforeUpdate

1,818 阅读2分钟

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

一、旧生命周期的问题

React官网已经在组件API文档中明确说明 UNSAFE_componentWillMount()UNSAFE_componentWillUpdate()UNSAFE_componentWillReceiveProps()这几个旧生命周期钩子即将过时,开发者们在新代码中应避免使用它们。因为它们确实存在很多问题,容易被误解和滥用。

(1)componentWillMount在SSR中这个方法会被多次调用,会导致重复触发多次,同时若在这个方法内绑定事件将无法解绑,会造成内存泄露,这个方法变得不够安全高效而逐步被放弃。

(2)componentWillReceiveProps外部组件多次频繁更新传入多次不同的props,会导致不必要的异步请求。

(3)componentWillupdate,更新前记录DOM状态,可能会做一些处理,与componentDidUpdate相隔时间如果过长会导致状态不可信。

二、新生命周期的替代

(1)getDerivedStateFromProps

static getDerivedStateFromProps(nextProps, nextState)

getDerivedStateFromProps在第一次的初始化组件以及后续更新的更新过程中(包括自身状态更新以及父传子)会被调用,返回一个对象作为新的state,返回null说明不需要在这里更新state。

[注意]  getDerivedStateFromProps是一个静态的类的方法,因此需要加上static关键字

简单来说,getDerivedStateFromProps的执行时机就是在组件初始化的时候以及组件后续更新的时候。同时getDerivedStateFromProps也可以最早的在父传子的时候获取到父组件传递给子组件的属性。由此可见,getDerivedStateFromProps很好的代替了componentWillMount以及componentWillReceiveProps。

static getDerivedStateFromProps(nextProps,nextState){
    if(nextProps.value!==undefined){
        return {
            current:nextProps.value
        }
    }
    return null
}

(2)getSnapshotBeforeUpdate

getSnapshotBeforeUpdate取代了componentWillUpdate,触发时机为update发生的时候,在render之后、dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。

比如列表更新后新的数据不断插入到数据前面,如何保证可视区依旧是之前看到的呢?(详细案例可以查看官网)

    getSnapshotBeforeUpdate(){
        return this.refs.wrapper.scrollHeight
    }
    
    componentDidUpdate(prevProps,prevState,preHeight){
        this.refs.wrapper.scrollTop+=this.refs.wrapper.scrollHeight-preHeight
    }
    .....