React的生命周期v16.4

发布于 / 学习

image

加载阶段(Mounting)

constructor()

组件刚加载的时候调用,在这里初始化state

static getDerivedStateFromProps(props, state)

组件每次被rerender的时候,包括在组件构建之后(虚拟dom之后,实际dom挂载之前),每次获取新的propsstate之后;每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state;配合componentDidUpdate,可以覆盖componentWillReceiveProps的所有用法

这个方法是静态的,无法通过this获取到组件的属性

具体使用:

Class ColorPicker extends React.Component {
    state = {
        color: '#000000'
    }
    static getDerivedStateFromProps (props, state) {
        if (props.color !== state.color) {
            return {
                color: props.color
            }
        }
        return null
    }
    ... // 选择颜色方法
    render () {
        .... // 显示颜色和选择颜色操作
    }
}
  • 本地拥有一个state,如果外部传进来一个state跟本地不相同的话,就返回更新本地的state
  • 如果外部传进来的跟本地的不相同就返回null不做任何处理

但是如果这样的话会有一个问题,color会只受props的影响,内部触发的改变不会修改,因为在新版本的生命周期中,组件内部setState也会触发这个生命周期,所以造成这样一个问题,下面来尝试解决:

Class ColorPicker extends React.Component {
    state = {
        color: '#000000',
        prevPropColor: ''
    }
    static getDerivedStateFromProps (props, state) {
        if (props.color !== state.prevPropColor) {
            return {
                color: props.color
                prevPropColor: props.color
            }
        }
        return null
    }
    ... // 选择颜色方法
    render () {
        .... // 显示颜色和选择颜色操作
    }
}

render

react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行

componentDidMount()

组件渲染之后调用,只会调用一次

更新阶段(Updating)

static getDerivedStateFromProps(props, state)

内部的setState或者forceUpdate也会触发这个生命周期

shouldComponentUpdate(nextProps, nextState)

组件接收到新的props或者state时调用,return true就会更新dom(使用diff算法更新),return false能阻止更新(不调用render

shouldComponentUpdate(nextProps, nextState) {
  return nextState.someData !== this.state.someData
}
  • 判断当前的statenextState是否相同,不相同的话渲染,相同的话不render

但是这时候又面临一个问题,如果someData是基本数据类型倒还好办,但是如果是引用数据类型的话,上面的判断恒为false

这时候为了解决这一问题:
Object.assign()
– 深浅拷贝/JSON.parse(JSON.stringify(data))
immutable.js
PureComponent

render()

更新数据,重新render

getSnapshotBeforeUpdate(prevProps, prevState)

触发时间: update发生的时候,在render之后,在组件dom渲染之前;返回一个值,作为componentDidUpdate的第三个参数;配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法

使用场景:

1s钟往div中插入一个<div>msg : number</div>,这样话滚轮会动,如果保持滚轮不动呢?


class SnapshotSample extends React.Component { constructor(props) { super(props); this.state = { messages: [],//用于保存子div } } handleMessage () {//用于增加msg this.setState( pre => ({ messages: [`msg: ${ pre.messages.length }`, ...pre.messages], })) } componentDidMount () { for (let i = 0; i < 20; i++) this.handleMessage();//初始化20条 this.timeID = window.setInterval( () => {//设置定时器 if (this.state.messages.length > 200 ) {//大于200条,终止 window.clearInterval(this.timeID); return ; } else { this.handleMessage(); } }, 1000) } componentWillUnmount () {//清除定时器 window.clearInterval(this.timeID); } getSnapshotBeforeUpdate () {//很关键的,我们获取当前rootNode的scrollHeight,传到componentDidUpdate 的参数perScrollHeight return this.rootNode.scrollHeight; } componentDidUpdate (perProps, perState, perScrollHeight) { const curScrollTop= this.rootNode.scrollTop; if (curScrollTop < 5) return ; this.rootNode.scrollTop = curScrollTop + (this.rootNode.scrollHeight - perScrollHeight); //加上增加的div高度,就相当于不动 } render () { return ( <div className = 'wrap' ref = { node => ( this.rootNode = node)} > { this.state.messages.map( msg => ( <div>{ msg } </div> ))} </div> ); }

componentDidUpdate(prevProps, prevState)

这个生命周期的作用是当propsstate更新之后,使用它更新DOM节点。如果使用不当,则查询页面会不停的调用查询的方法,不停的执行刷新操作。因此,需要给新增的方法增加一个标志,通过这个标志,判断,如果新增成功,则调用一次查询方法,否则,则不调用

基本使用:
开发者在等界面完全render后进行一些请求或者其他操作,比如setState(),大多数情况下,为了避免循环调用这个函数,官方要求在函数内加一行判断,以确保不会陷入无限循环,例:

constructor(props){
    super(props);
    this.tmpData={};
    // ... Other code
}

produce(data){
    this.tmpData = arrayDeepCopy(data)   // 假设生产出来的数据是{a: '123', b:{c: '234'}}
    this.setState({data: data})
}

componentDidUpdate(prevProps, prevState){
    if ( !arrayIdentical(this.tmpData, this.state.data) ){
        // fetchUserData(userID)
    }
}

卸载阶段

componentWillUnmount()

组件销毁时调用,常用于关闭一些页面上的定时器

Error Handling(错误处理)

componentDidCatch(error,info)

任意一处js报错都可以在这里捕获

总结

  • 新增了getDerivedStateFromPropsgetSnapshotBeforeUpdate来代替弃用的三个钩子函数(componentWillMount、componentWillReceivePorps,componentWillUpdate
本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可
本文链接: https://www.ahwgs.cn/reactdeshengmingzhouqiv16-4.html