react 生命周期钩子函数的触发时机

react 生命周期钩子函数

老的生命周期

  • 初始化阶段

    // 组件将要被挂载,render 之前最后一次修改状态的机会
    componentWillMount () {} // 不安全,将被新生命周期替代
    
    // 渲染,只能访问 this.props 和 this.state,不允许修改状态和 dom 输出
    render () {}
    
    // 成功 render 并渲染完成真实 dom 之后触发,可以修改 dom
    componentDidMount () {}
    
  • 运行中阶段

    // 子组件将要接收 props, 父组件改变 传给子组件的属性时调用
    componentWillReceiveProps(nextProps) { // 不安全,将被新生命周期替代
        console.log("更新前的 props", this.props)
        console.log("更新后的 props", nextProps)
    }
    
    // 组件是否需要更新,返回 true 更新;返回 false 不更新,可以用来优化组件性能
    shouldComponentUpdate(nextProps, nextState) {
        // 更新前状态与更新后状态相同,就返回 false,不更新
        if (JSON.stringify(this.state) === JSON.stringify(nextState)) return false
    
        return true
    }
    
    // 组件更新之前调用
    componentWillUpdate(nextProps, nextState) { // 不安全,将被新生命周期替代
        console.log("更新前的数据", this.state)
        console.log("将要更新的数据", nextState)
    }
    
    // 渲染,只能访问 this.props 和 this.state,不允许修改状态和 dom 输出
    render () {}
    
    // 组件更新完成后调用
    componentDidUpdate(prevProps, prevState) {
        console.log("更新前的数据", prevState)
        console.log("更新后的数据", this.state)
    }
    
  • 销毁阶段

    // 在删除组件之前进行清理操作,比如计时器和事件监听器
    componentWillUnmount () {}
    

在老的生命周期中存在一些问题

  1. componentWillMount 这个钩子函数,在 ssr 中这个方法将会被调用多次,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏。

  2. componentWillReceiveProps 这个钩子函数,在外部组件多次、频繁传入不同的 props 时,会导致产生不必要的异步请求。

  3. componentWillUpdata 这个钩子函数,可以在更新前记录 dom 状态,但是如果与 componentDidUpdata 钩子函数相隔时间过长,会导致记录的状态不可信

针对以上三个钩子函数的 bug 问题,官方给了出新的生命周期钩子函数

  • getDerivedStateFromProps 钩子函数

    • 作用:取代 componentWillMount 钩子函数与 componentWillReceiveProps 钩子函数
    • 用法:第一次的初始化组件以及后续的更新组件时调用,返回一个对象作为新的 state,返回 null 则说明不需要在这里更新 state
    import React, { Component } from 'react'
    
    class Child extends Component {
      state = {
        abc: 'abc'
      }
      render() {
        return (
          <div>
            <p>child --- {this.props.title}</p>
            <p>{this.state.msg}---{this.state.abc}</p>
          </div>
        )
      }
    
      // 初始化组件以及更新组件都会触发这个钩子函数
      static getDerivedStateFromProps(props, state) {
        console.log(props, state)
        return { // 这个对象会结合之前的 state,返回一个新的 state
          msg: 456
        }
      }
    }
    
    export default class App extends Component {
      state = {
        title: '标题'
      }
      render() {
        return (
          <div>
            <p>app</p>
            <button onClick={() => this.setState({title: '标题2'})}>
              click
            </button>
    
            <Child title={this.state.title} />
          </div>
        )
      }
    }
    
    
  • getSnapshotBeforeUpdate 钩子函数

    • 作用:取代 componentWillUpdata 钩子函数
    • 用法:在 render 之后 componentDidUpdata 钩子之前触发,返回一个值,作为 componentDidUpdata 钩子函数的第三个参数
    import React, { Component } from 'react'
    
    class Child extends Component {
      render () {
        return (
          <div>
            <p>child---{this.props.title}</p>
          </div>
        )
      }
    
      // 这个钩子函数需要与 componentDidUpdate 配合使用,不然会报警告
      getSnapshotBeforeUpdate = (prevProps, prevState) => {
        console.log(prevProps)
        return 100
      }
    
      componentDidUpdate(prevProps, prevState, value) {
        console.log(value)  // 100
      }
    
    
    }
    
    export default class App extends Component {
      state = {
        title: '标题'
      }
      render() {
        return (
          <div>
            <p>app</p>
            <button onClick={() => this.setState({title: '标题2'})}>
              click
            </button>
    
            <Child title={this.state.title}/>
          </div>
        )
      }
    }
    

react 中性能优化方案

  • shouldComponentUpdate 钩子函数,控制组件自身或者子组件是否需要更新,尤其在子组件非常多的非常多的情况下,需要进行优化。

  • PureComponent 会自动比较新 props 跟旧 props,新 state 和 旧 state,决定 shouldComponentUpdata 钩子函数返回 true,还是 false。注意:如果 state 和 props 永远不会变,那么 PureComponent 并不会比较快,因为 shallowEqual 也需要时间。

    import React, { Component, PureComponent } from 'react'
    
    class Child extends PureComponent { // 继承 PureComponent 的组件会自动做性能优化
      render () {
        return (
          <div>
            <p>child --- {this.props.title}</p>
          </div>
        )
      }
    }
    
    export default class App extends Component {
      state = {
        title: '标题'
      }
      render() {
        return (
          <div>
            <p>app</p>
    
            <Child title={this.state.title} />
          </div>
        )
      }
    }
    
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值