前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React的生命周期v16.4

React的生命周期v16.4

作者头像
w候人兮猗
发布2020-07-01 16:56:42
7730
发布2020-07-01 16:56:42
举报
文章被收录于专栏:w候人兮猗的博客
image
image

加载阶段(Mounting)

constructor()

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

static getDerivedStateFromProps(props, state)

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

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

具体使用:

代码语言:javascript
复制
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也会触发这个生命周期,所以造成这样一个问题,下面来尝试解决:

代码语言:javascript
复制
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

代码语言:javascript
复制
shouldComponentUpdate(nextProps, nextState) {
  return nextState.someData !== this.state.someData
}
  • 判断当前的statenextState是否相同,不相同的话渲染,相同的话不render

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

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

render()

更新数据,重新render

getSnapshotBeforeUpdate(prevProps, prevState)

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

使用场景:

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

代码语言:javascript
复制
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(),大多数情况下,为了避免循环调用这个函数,官方要求在函数内加一行判断,以确保不会陷入无限循环,例:

代码语言:javascript
复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年11月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 加载阶段(Mounting)
    • constructor()
      • static getDerivedStateFromProps(props, state)
        • render
          • componentDidMount()
          • 更新阶段(Updating)
            • static getDerivedStateFromProps(props, state)
              • shouldComponentUpdate(nextProps, nextState)
                • render()
                  • getSnapshotBeforeUpdate(prevProps, prevState)
                    • componentDidUpdate(prevProps, prevState)
                    • 卸载阶段
                      • componentWillUnmount()
                      • Error Handling(错误处理)
                        • componentDidCatch(error,info)
                        • 总结
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档