react 常用生命周期

以下UNSAFE_开头的周期都是官方将要废弃的周期

保留UNSAFE_前缀还可以继续使用 在最新的16.9中将抛出warning 在17.0的大版本中彻底移除componentWillMount、componentWillUpdate、componentWillReceiveProps这三个生命周期 帮助理解 但不建议继续使用和学习

组件挂载时

constructor()

  • class的构造器 继承父类Component可以做一些基本的绑定操作
  • 可以绑定ref(这里指React.createdRef()这种创建方式)、给事件绑定this或是state根据props获取的默认数据等
  • 只会触发一次!!

static getDerivedStateFromProps(props, state)

  • 新出的静态周期 为了替代 componentWillReceiveProps
  • 只有在父组件重新渲染 props发生变化才会触发
  • this.setState()不会触发getDerivedStateFromProps
  • 如果想要触发 需要this.forceUpdate(callback)=> {小常识:有时一些变量我们无需在视图层上展示 就会偷懒直接存到组件内部的this上 当我们某些条件下修改这个值的时候并不会触发重新渲染 这个时候我们就可以this.forceUpdate()手动触发告诉react我要渲染 给我渲染!! 也请记住 这样做会直接跳过本组件的shouldComponentUpdate()直接进行渲染 所以请尽量避免这么干}
  • 在此周期内部无法访问到this
    很多刚看到这个周期的人可能都不太理解 我们在componentWillReceiveProps里可以根据当前props和下一次props的变更去进行this.setState或是派生数据之类的做法 可在这个周期里 我们无法进行比较 那我们该怎么办

在我个人看来这个周期是主要为了能更好的派生数据 很多时候我们当前需要用到的数据来自于props而我们也无法直接使用props需要进行二次派生 这个时候我们就可以用这个周期将派生的数据存在state里以供使用 而不是频繁的触发componentWillReceiveProps不停的render()

static getDerivedStateFromProps(props, state) {
    if (state.data.length === 0 && props.data.length) {
        return { data: props.data }
    }
    return null
}

此方法的用法很好理解 是否需要更新state 不需要就return null 如果需要 可以根据props和上一次的state做一些简单的比较 return的对象就会更新state

如果我们只想要更新state里的data 但不更新其他的 我们不需要像redux里一样return {...state, data} 我们只需要更新自己想要更新的那一条就可以了

对于上面讲到的很多时候需要根据当前props和下一次进行比较而做一些业务或是更新 这个时候我们就可以考虑使用componentDidUpdate 甚至是 shouldComponentUpdate(当然 考虑到周期的取名和合理性 我们还是尽量避免这种姿势)

UNSAFE_componentWillMount()

  • 此周期在render前触发 有的人喜欢在这里做一些订阅或是监听的操作 建议移到constructor或是componentDidMount

render()

  • 更新组件的propsstate返回一个React元素/节点
  • render是一个纯函数 没有副作用 所以我们不要在render里做this.setState类似这种操作
  • 不负责最后的渲染工作
  • nullboolean不会被渲染

componentDidMount()

  • 组件挂载后 官方的话说就是已经插入dom节点 我们需要做一些绑定的操作可以在这里
  • 方便做一些订阅或是监听在这里
  • 绑定的ref在这是拿不到的
  • 我们也可以在这里做一些修改state的操作 那将会触发再次render(并非浏览器页面的再次渲染) 但尽量避免这么干 至于为什么 这还用说吗
  • constructor一样 只会触发一次

update更新时

既然是更新时 那就代表 下面这些会按顺序全部都触发!
当然 不完全是这样 组件内部state的更新不会触发UNSAFE_componentWillReceivePropsgetDerivedStateFromProps
但如果是组件内部的state更新了 子组件用到了这里的state(也就是子组件的props 父组件的state) 则会遵循规则 子组件会触发这些周期 组件之间都会遵循这些机制

UNSAFE_componentWillReceiveProps(nextProps, nextState)

    UNSAFE_componentWillReceiveProps(nextProps, nextState) {
        if (this.state.visible !== nextProps.visible) {
            this.setState({ visible: nextProps.visible })
        }
    }
  • 接收两个参数 分别是下一次的props和下一次的state 我们可以在里面比较两次的变化然后to do something
  • 但也因为如此 很容易出现一些我们无法预估的bug出现

static getDerivedStateFromProps(props, state)

  • 同上述一样
  • 注意组件内部的state直接变化不会触发这里 若有需要 可以this.forceUpdate(callback) 同上
  • 如果是props的数据变化触发此周期 再次派生state 这里的触发是因为props 而不是单纯的state变化

shouldComponentUpdate(nextProps, nextState)

官方认为state每次更新了 就应该重新render 大部分情况下我们应该遵循渲染的规则

大多出现在需要优化的地方propsstate不可控 频繁触发render的时候 如长时间的倒计时等

只作为优化而存在 也可参考使用PureComponent浅比较组件

若你使用的是纯函数式组件也想达到此效果或是目的可以使用React.memo()

如果你也在同时学习或使用hook 你也可以使用useMemo

    shouldComponentUpdate(nextProps, nextState){
        if (this.props.value !== nextProps.value) {
            return true
        }
        return false
    }
  • 接收两个参数 下一次拿到的props和下一次拿到的state
  • 这个周期是render渲染前的最后一个周期 代表是否render(除开componentWillUpdate将要废弃)。
  • 在最后一定要返回一个false代表不渲染 否则会出现意想不到的影响。
  • return false前可以根据当前的this.props || this.state等等里面的某些值进行判断 需要渲染就 return true
  • 如果判断是否渲染的条件里要用到循环或是JSON.parse JSON.stringify等序列化 反序列化的操作 性能可能更差 不如不用

UNSAFE_componentWillUpdate(nextProps, nextState)

  • 在更新发生前被立即调用 你不能在此调用this.setState()dispatch等操作触发组件再次更新
  • 在这个时候做任何操作其实都是不合理的 不论是导致props还是state的改变再次导致重复性的工作 副作用不可想象
  • 确实有需要 请移步componentDidUpdate
  • 官方将其废除这个做法非常的nice!!

getSnapshotBeforeUpdate(prevProps, prevState)

  • 这个方法会在把渲染结果提交到DOM之前被调用 它可以返回一个参数
  • 这个参数被componentDidUpdate(prevProps, prevState, snapshot)方法的第三个参数接收
  • 官方的说法是组件能在发生更改之前从DOM中捕获一些信息(例如滚动位置)
  • 我是还没有遇到过使用场景太细节也不清楚

render()

  • 各种将数据过滤转译成字符串 diff算法 更新部分更改部分等等操作 然后生成节点 同上

componentDidUpdate(prevProps, prevState, snapshot)

    componentDidUpdate(prevProps, prevState, snapshot) {
        if (this.props.value !== prevProps.value) {
          this.changeValue(this.props.value)
        }
    }
  • 在更新发生后被立即调用。可以在DOM更新完之后做一些收尾的工作 也就是说 首次挂载一定不会触发 别理解错
  • 我们可以在这里做一些原来使用UNSAFE_componentWillUpdate所做的一些根据上一次props state和下一次的不同而触发的逻辑或是业务需要
  • 但和UNSAFE_componentWillUpdate不同 这里接收到的是上一次的propsstate

卸载时

componentWillUnmount()

  • 我们可以在这边做收尾工作 清除计时器、订阅、监听等等
  • 大多数时候会出现一些this.setState不能对不存在的组件进行修改的警告甚至是报错
  • 其实就是组件已经卸载(销毁)了 异步的this.setState还在修改已销毁的state 当然拿不到
  • 所以有时我们需要以下种种姿势
componentWillUnmount() {
    this.setState = (state, callback) => { return }
    window.removeEventListener()
    clearInterval()
}

这是本人曾经学习到使用后来一点点积累的笔记整理出来的 仅供参考 如果有写的不对的有是遗漏 欢迎及时指出
掘金 上也有一样的文章但我这边经常登不上去 很不稳定 决定同步到上来

你可能感兴趣的:(react 常用生命周期)