天天看点

react17 生命周期场景解释

一、废除的生命周期

官网文档指出使用这些生命周期的代码会在未来版本的react中更容易产生bug,尤其是对于异步渲染的版本

由于未来采用异步渲染机制,所以即将在17版本中去掉的生命周期钩子函数

componentWillMount

componentWillRecieveProps

componentWIllUpdate

二、新增的生命周期

static getDerivedStateFromProps(nextProps, prevState) {}

用于替换componentWillReceiveProps,可以用来控制 props 更新 state 的过程;它返回一个对象表示新的 state;如果不需要更新,返回 null 即可

在每次渲染之前都会调用,不管初始挂载还是后面的更新都会调用,这一点和componentWillReceiveProps不同(只有当父组件造成重新渲染时才调用

简单的理解就说从props中获取state,这个生命周期的功能实际上就是将传入的props映射到state上面

getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state

如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾

getSnapshotBeforeUpdate() {}

在最近的更改被提交到DOM元素前,使得组件可以在更改之前获得当前值,此生命周期返回的任意值都会传给componentDidUpdate()。

用于替换 componentWillUpdate,该函数会在update后 DOM 更新前被调用,用于读取最新的 DOM 数据,返回值将作为 componentDidUpdate 的第三个参数

在最新的渲染数据提交给DOM前会立即调用,它让你在组件的数据可能要改变之前获取他们

componendDidCatch(error, info)

如果一个组件定义了componentDidCatch生命周期,则他将成为一个错误边界(错误边界会捕捉渲染期间、在生命周期方法中和在它们之下整棵树的构造函数中的错误,

就像使用了try catch,不会将错误直接抛出了,保证应用的可用性)

三、下面来看看实际应用场景分析:

/*
 * @Descripttion: react17 生命周期测试
 * @version: 
 * @Author: lhl
 * @Date: 2021-03-04 14:51:12
 * @LastEditors: lhl
 * @LastEditTime: 2021-03-26 18:46:49
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types' // prop代表父组件传递过来的值,types代表类型 简单来说就是用来校验父组件传递过来值的类型


// 类组件 
/*
    1.挂载时顺序
    constructor() --> static getDerivedStateFromProps(props, state) --> render() --> componentDidMount()

    2.更新时顺序
    static getDerivedStateFromProps(props, state) --> shouldComponentUpdate() --> render() --> 
    static getSnapshotBeforeUpdate(prevProps, prevState) --> componentDidUpdate()

    3.卸载 (比如页面切换)
    componentWillUnmount()

    在 Fiber 机制下,render 阶段是允许暂停、终止和重启的。废弃的生命周期钩子函数,它们都处于render阶段,都可能被重复执行
    在 componentWillReceiveProps 和 componentWillUpdate 里滥用 setState 导致重复渲染死循环的
    forceUpdate(callback) - 组件强制更新,会跳过shouldComponentUpdate
*/
export default class LifeCycle extends Component {
    // constructor()用来做一些组件的初始化工作,如定义this.state的初始内容 为事件处理函数绑定实例
    constructor(props){
        // super(props)用来调用基类的构造方法( constructor() ), 也将父组件的props注入给子组件,供子组件读取(组件中props只读不可变,state可变)
        super(props)
        this.state = {
            count: 0
        }
        console.log('constructor')
    }
    // static propTypes = {
    //     prop: PropTypes // react里的defaultProps来设置默认的props值
    // }

    static getDerivedStateFromProps(props, state){
        console.log(props, state,'getDerivedStateFromProps')
        return true
    }

    componentDidMount(){
        console.log('componentDidMount')
    }

    // 根据更新后的state或props判断是否重新渲染DOM,返回值为布尔值,常用来性能优化
    /**
     * 判断是否需要更新视图,执行后面的render方法
     * 1. 如果返回 false ,则不需要执行后面的render方法,视图也不会改变
     * 2. 返回true, 需要执行render方法,视图也会对应的改变
     */
    // 下一个和当前状态对比 nextState === this.state.xxx 没有变化就 return false 否则 true
    shouldComponentUpdate(nextProps, nextState){
        console.log(nextProps, nextState, 'shouldComponentUpdate')
        return true
    }
    
    // 该函数会在update后 DOM 更新前被调用,用于读取最新的 DOM 数据,返回值将作为 componentDidUpdate 的第三个参数
    getSnapshotBeforeUpdate(prevProps, prevState){
        console.log(prevProps, prevState,'getSnapshotBeforeUpdate')
        return true
    }

    // state或props更新后调用
    componentDidUpdate(props, state, snapshot){
        console.log(props, state, snapshot,'componentDidUpdate')
    }

    // 组件销毁或卸载时调用
    componentWillUnmount(){
        console.log('componentWillUnmount')
    }

    // 错误处理
    // 后代组件跑出错误时调用,并返回一个值以更新state
    static getDerivedStateFromError(callback){
        console.log(callback)
    }
    
    // 后代组件抛出错误后调用,参数info包含有关组件错误的栈信息
    componentDidCatch(error, info){
        console.log(error, info)
    }

    handleChange = () => {
        this.setState({
            count: 12
        })
    }

    // 渲染React组件  PureComponet 和 shouldComponentUpdate 处理渲染性能优化问题
    // 初始化
    // setState()在任何情况下都会导致组件的重新渲染,即使state未发生变化
    // 只要父组件重新渲染了,那么子组件就会重新渲染
    render() {
        console.log('render')
        const { count } = this.state
        return (
            <div>
                <h1>react 17 生命周期</h1>
                <button onClick={this.handleChange}>更改状态{count}</button>
            </div>
        )
    }
}

LifeCycle.propTypes = {
    name: PropTypes.string
};