# react 的生命周期

110 阅读17分钟

react 的生命周期

生命周期在 react 里面还是很重要的哈,使用的也是相对比较频繁,然后本博文主要说一下 react 生命周期的使用。

为啥需要生命周期

我们看一个例子,我们做一个页面,里面显示一句话,然后这句话的透明度会循环的从1变到0,然后有一个按钮,点击按钮的时候可以把这个组件给注销掉,具体效果就是这个样子的。

在这里插入图片描述

OK,下面我们写一下这个案例,我们先不管透明度,先写一个按钮,点击可以把整个组件注销掉。

    <!-- 此处必须写 text/babel -->
    <script type="text/babel">

        // 创建组件
        class Life extends React.Component {

            death = () => {
                // 卸载组件  注销组件在节点
                ReactDOM.unmountComponentAtNode(document.getElementById('app'))
            }

            // 初始化渲染,页面更新时候调用
            render() {
                return (
                    <div>
                        <h2>我是𝒆𝒅.太帅了怎么办?</h2>
                        <button onClick={this.death}>直接帅死</button>
                    </div>
                )
            }
        }
        // 渲染组件
        ReactDOM.render(<Life />, document.getElementById("app"))
    </script>

OK,保存代码然后刷新浏览器查看效果:

在这里插入图片描述 可以啦,点击按钮就可以注销整个组件了。

接下来就是透明度,我们可以在状态维护透明度,让他在两秒钟的时间里,使透明度从1变到0,然后不停地循环。这时候我们需要写一个定时器,每个200毫秒,透明度减少 0.1。

初始一下状态

state = { opacity: 1 }

编写一个定时器

setInterval(() => {
   let { opacity } = this.state
   opacity -= 0.1
   if (opacity <= 0) opacity = 1
   this.setState({ opacity })
}, 200)

下面有一个问题啊,定时器编写好了,放在哪里啊,我们需要在页面刷新出来就开始执行。

我们知道页面刷新之后会自动执行 render 函数,所以说我们把定时器放到 render 函数里面试一下。

            // 初始化渲染,页面更新时候调用
            render() {
                setInterval(() => {
                    let { opacity } = this.state
                    opacity -= 0.1
                    if (opacity <= 0) opacity = 1
                    this.setState({ opacity })
                }, 200)
                return (
                    <div>
                        <h2 style={{ opacity: this.state.opacity }}>我是𝒆𝒅.太帅了怎么办?</h2>
                        <button onClick={this.death}>直接帅死</button>
                    </div>
                )
            }

保存刷新看效果。

在这里插入图片描述 我们看到效果,文字闪烁的越来越快,好像不是两秒钟从1到0,为啥呢?其实这是一个重大的bug!!! 因为我们在 render 中写了一个定时器,每隔200毫秒就会修改修改状态值,但是状态值的修改会驱动页面更新,页面更新就会重新执行 render,render执行就会在创建一个 定时器,所以死循环,不抓紧停止,电脑会崩掉。

所以说我们不能把定时器写在 render 当中去!当然,我们可以在写一个按钮,点击按钮在开始实现颜色的淡化。但是这种方法就不写了,因为刷新完页面,还需要再次点击才会生效,所以说我们用生命周期钩子。

render 函数,不用写成箭头函数的形式,因为他是 React 自动执行的,用于初始化渲染和更新组件时候使用,同时他还有一个兄弟方法 componentDidMount ,他会在组件挂在完成之后执行一次。这两个函数都是生命周期函数,也叫生命周期钩子。

所以说我们可以把定时器写到componentDidMount声明函数当中,让定时器在组件挂载完成后自动启动。

            // 组件挂在完毕
            componentDidMount() {
                this.timer = setInterval(() => {
                    let { opacity } = this.state
                    opacity -= 0.1
                    if (opacity <= 0) opacity = 1
                    this.setState({ opacity })
                }, 200)
            }

OK。这样我们保存代码刷新浏览器查看一下效果。

在这里插入图片描述 OK,这样透明度渐变的效果就实现了,但是发现我们点击按钮之后,组件确实注销了,但是控制台报错了。为啥呢,就是我们组件注销了,但是定时器依旧执行,组件都没了,所以找不到状态 state报错的,所以说,我们需要在组件注销之前把定时器清了,可以直接写在 death 方法, 也可以写在另一个生命周期函数 componentWillUnmount 中, 他是在组件将要被卸载的时候被调用。

            // 组件挂在完毕
            componentDidMount() {
                this.timer = setInterval(() => {
                    let { opacity } = this.state
                    opacity -= 0.1
                    if (opacity <= 0) opacity = 1
                    this.setState({ opacity })
                }, 200)
            }

            // 组件将要被卸载
            componentWillUnmount() {
                clearInterval(this.timer)
            }

OK,这样就实现了我们案例的效果。

在这里插入图片描述 好的,这样我们就实现了案例效果,这个案例我们一共用到了三个生命周期 componentDidMountcomponentWillUnmountrender,好了,这部分就这样,我要睡觉了,现在都是凌晨五点半了,又一个通宵,明天起床之后继续把各个生命周期钩子都讲一下。晚安啦宝子们,累死我了。

【本部分相关代码资料】:我是𝒆𝒅. 的 gitee

react 旧的生命周期函数-挂载流程

react 有两套生命周期函数,我们先看一下旧的,再说一下新的,为啥有新的还看旧的呢,因为新的还有没推广,旧的还是很多人开发的首选,从17版本之后,新的才开始使用,我们看一下旧的生命周期函数在组件创建销毁过程中的挂载。

首先明白,什么是生命周期,他有什么特点

  1. 组件从创建到死亡会经历一些特定的阶段,这些特定的阶段就是生命周期钩子。
  2. React组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用。
  3. 我们在定义组件的时候,会在特定的生命周期回调函数中做特定的工作。
  4. 生命周期的挂载销毁顺序,与编码前后顺序无关。
  5. 生命周期钩子不需要我们主动调用,react 会在适宜的时间自动执行。
  6. 我们代码里面不写生命周期,不代表生命周期钩子不执行。

先看一张图片:

在这里插入图片描述

上边这张图片呢,就是旧版的生命周期流程图。

我们一部分一部分的看,然后呢,我们还是结合一个案例来看一下生命周期的挂载流程,我们写一个案例,一个页面上有一个标签,显示一个数字,然后有两个按钮,点击第一个按钮,实现标签上的数字加1操作,点击另一个按钮,把组件注销掉。

    <!-- 此处必须写 text/babel -->
    <script type="text/babel">

        // 创建组件
        class Count extends React.Component {
        
			state = { count: 0 }

            // 加 1 按钮回调
            add = () => {
                const { count } = this.state
                this.setState({ count: count + 1 })
            }

            // 卸载组件
            death = () => {
                ReactDOM.unmountComponentAtNode(document.getElementById('app'))
            }
            
            // 初始化渲染,页面更新时候调用
            render() {
                const { count } = this.state
                return (
                    <div>
                        <h2>当前求和结果:{count}</h2>
                        <button onClick={this.add}>点击 + 1</button>
                        <button onClick={this.death}>卸载组件</button>
                    </div>
                )
            }
        }
        // 渲染组件
        ReactDOM.render(<Count />, document.getElementById("app"))
    </script>

上面就是这个组件的初始代码,

在这里插入图片描述 OK,效果实现了,然后我们一部分一部分的看,我们先看挂载。

挂载时 生命周期挂载流程

在这里插入图片描述

也就是先看我红色箭头标注的这条线,一共有涉及了五个生命周期钩子,分别是 构造器函数组件将要被挂载组件渲染组件挂载完成组件将要被卸载

我们要验证生命周期钩子的挂载流程,其实只要简单的调用一下钩子,然后看看一下打印顺序就可以啦把!

那我们在上边案例里面把这五个声明周期钩子都写一下。

    <!-- 此处必须写 text/babel -->
    <script type="text/babel">

        // 创建组件
        class Count extends React.Component {

            // 构造器
            constructor(props) {
                console.log('Count-constructor')
                super(props)
                // 初始化状态
                this.state = { count: 0 }
            }

            // 加 1 按钮回调
            add = () => {
                const { count } = this.state
                this.setState({ count: count + 1 })
            }

            // 卸载组件
            death = () => {
                ReactDOM.unmountComponentAtNode(document.getElementById('app'))
            }


            // 组件将要挂载的钩子
            componentWillMount() {
                console.log('Count-componentWillMount')
            }

            // 组件挂载完成的钩子
            componentDidMount() {
                console.log("Count-componentDidMount")
            }

            // 组件将要卸载
            componentWillUnmount() {
                console.log("Count-componentWillUnmount")
            }

            // 初始化渲染,页面更新时候调用
            render() {
                console.log('Count-render')
                const { count } = this.state
                return (
                    <div>
                        <h2>当前求和结果:{count}</h2>
                        <button onClick={this.add}>点击 + 1</button>
                        <button onClick={this.death}>卸载组件</button>
                    </div>
                )
            }
        }
        // 渲染组件
        ReactDOM.render(<Count />, document.getElementById("app"))
    </script>

OK,上边写完了五个钩子,在钩子里面分别打印出钩子的名称,我们打开控制台看一下输出结果。

在这里插入图片描述 好,我们刷新完浏览器发现,四个生命周期钩子都已经成功执行了。constructor 构造器钩子 --> componentWillMount 组件即将挂载 --> render 组件渲染 --> componentDidMount 组件渲染完成 。 然后当我们点击卸载组件按钮的时候,componentWillUnmount 组件将要被卸载 钩子也被执行。

OK,这就是我们组件挂载时这部分钩子的执行情况。

接下来我们看右边,右边其实有三条线。

在这里插入图片描述

我在图上标注了一下,分别是 第一条 组件状态修改 紫色线第二条 组件强制更新 黄色线第三条 父组件渲染 绿色线

状态数据修改 生命周期挂载流程

我们先从简单的来,看第一条,当组件状态数据修改的时候,触发了 五个生命周期钩子,分别是 shouldComponentUpdate 组件是否应该被更新componentWillUpdate 组件将要被更新render 组件渲染componentDidUpdate 组件更新完成componentWillUnmount 组件将要被卸载。同样我们需要先写一下生命周期调用一下,怎么触发状态数据修改呢?我们只要点击一下 加1 按钮,状态数据 count 就可以被 + 1 ,数据就变了,触发这个 黄色线 吧?

当数据变化,首先触发一个shouldComponentUpdate 组件是否应该被更新钩子,这是干啥用的呢?比较特殊,我们单独说一下,先不管怎么用,我们先像之前钩子一样打印一下可以吧?

            // 组件是否应该被更新
            shouldComponentUpdate() {
                console.log("Count-shouldComponentUpdate")
            }

保存,我们点击按钮+1看一下钩子打印的啥。

在这里插入图片描述 点击按钮实现 +1 操作,生命周期走了,因为打印数据了,但是同时控制台报错了,而且我们看到页面的数据没有变。看一下报错信息,报错内容大体是,这个生命周期返回了一个 undefined,这个是肯定的吧,因为我们除了打印数据啥也没有return,但是他说这个生命周期需要返回一个 true 或者是 false

知道原因了我们改一下。返回一个 true

            // 组件是否应该被更新 (控制组件更新的阀门)
            shouldComponentUpdate() {
                console.log("Count-shouldComponentUpdate")
                return true
            }

保存,重复上一步骤,看结果。

在这里插入图片描述 返回 true 之后呢,一切都正常了,那如果返回 false 呢?测试一下。

            // 组件是否应该被更新 (控制组件更新的阀门)
            shouldComponentUpdate() {
                console.log("Count-shouldComponentUpdate")
                return false
            }

保存,重复上一步骤,看结果。

在这里插入图片描述

当我们把返回值改成 false 之后,再点击按钮,生命周期钩子执行,但是渲染的钩子 render 很显然没执行啊,因为我们给 render 钩子里面打印了,这里没有输出,页面也没变。

总结: shouldComponentUpdate 组件是否应该被更新 生命周期钩子,必须要有一个 Boolean 类型的返回值,作为控制组件能否更新的阀门。当返回值为 true 时,后面声明周期钩子可以继续按顺序执行,页面正常更新。当返回值为 false 的时候,后面生命周期钩子不再执行,页面不会更新。如果我们不写这个生命周期,那么这个生命周期默认永远返回 true

OK,继续这条线,我们设置 true,让后边的生命周期钩子依次执行查看挂载流程,rendercomponentWillUnmount 之前写了,我们就把缺少的两个钩子补充完整。

            // 组件将要被更新
            componentWillUpdate() {
                console.log("Count-componentWillUpdate")
            }

            // 组件更新完成
            componentDidUpdate() {
                console.log("Count-componentDidUpdate")
            }

保存刷新,看一下执行结果。

在这里插入图片描述 OK,第二条线的钩子可以依次执行。上面这部分就是 挂载时 和 状态数据改变触发的生命周期挂载流程。

【本部分相关代码资料】:我是𝒆𝒅. 的 gitee

强制更新 生命周期回调

这一部分我们看第二条线,也就是黄色的,比第一条线复杂一点,但是还好。

在这里插入图片描述

第二条线是在什么时候触发呢?就是强制刷新页面,啥意思呢,就是我们页面挂载完成,状态数据也没有变化,我就是神经病,就像让他强制给我刷新一下页面,这就触发了这条生命周期。

我们在之前的案例上面,加一个按钮,点击按钮的时候,强制更新页面。

// 初始化渲染,页面更新时候调用
render() {
    console.log('Count-render')
    const { count } = this.state
    return (
        <div>
            <h2>当前求和结果:{count}</h2>
            <button onClick={this.add}>点击 + 1</button>
            <button onClick={this.death}>卸载组件</button>
            <button onClick={this.force}>不更改任何数据,强制更新</button>
        </div>
    )
}

然后我们需要写一下 force 方法:

            // 强制更新回调
            force = () => {
                this.forceUpdate()
            }

好的,我们点击按钮之后,强制更新页面,这时候这条线会触发三个生命周期函数,加上卸载是四个。分别是 componentWillUpdate 组件将要被更新render 组件渲染componentDidUpdate 组件更新完成componentWillUnmount 组件将要被卸载。这时候,我们是强制更新,所以说 shouldComponentUpdate 组件是否应该被更新 就不管用了,这个一定要知道哈,就算我在 shouldComponentUpdate 组件是否应该被更新 里面返回了 false 也白瞎,根本没有触发,如果触发了就不叫强制了对吧。

好的,生命周期在状态数据改变时候案例已经写完了,我们直接看一下效果就可以了。

在这里插入图片描述 OK,是没有问题的,就是正常使用,不用过多的解释。

【本部分相关代码资料】:我是𝒆𝒅. 的 gitee

父组件render流程 生命周期回调

下面我们看 旧版本生命周期的 最后一条线 第三条线 也就是 绿色那条。

在这里插入图片描述

这个怎么触发呢?我们重新写一个案例哈,上面案例我们写了一个 Count 组件,我们现在需要写一个 父子组件调用。

我们创建一个A组件,创建一个B组件, A组件就显示一个名字,但是里面有一个状态值,还有一个按钮,点击按钮的时候,A组件的状态值改变;B组件有一个名字展示,但是还需要展示一个数据,展示的数据是A组件传进来得状态值,当A组件按钮点击之后A组件的状态改变,B组件展示的A组件传进来得状态值也会对应改变。这里,A作为父组件,B作为子组件,因为B组件嵌套在 A组件里面的。

首先我们初始一下这个需求的代码,很简单,不多说,直接看代码。

    <!-- 此处必须写 text/babel -->
    <script type="text/babel">

        // 父组件 A
        class A extends React.Component {

            state = { car: '红旗' }

            changeCar = () => {
                this.setState({ car: '比亚迪' })
            }

            render() {
                return (
                    <div>
                        <div>A 组件</div>
                        <button onClick={this.changeCar}>换车</button>
                        <B car={this.state.car} />
                    </div>
                )
            }
        }

        // 子组件 B
        class B extends React.Component {

            render() {
                console.log("B---render")
                return (
                    <div>B 组件,接受到的车是:{this.props.car}</div>
                )
            }
        }

        // 渲染组件
        ReactDOM.render(<A />, document.getElementById("app"))
    </script>

保存刷新,看一下效果:

在这里插入图片描述 好,效果实现,就是这个样子。

我们看上边的图,当父组件数据变了,子组件会触发五个生命周期,分别是 componentWillReceiveProps 组件将要接收到新传进的参数钩子shouldComponentUpdate 组件是否应该被更新componentWillUpdate 组件将要被更新render 组件渲染componentDidUpdate 组件更新完成

我们按照顺序来看,第一个声明周期,我们不知道怎么用,写在B组件写一下呗。他既然是 组件将要接收到新传进的参数钩子,所以说应该会接收一个参数吧?似的,接收的参数就是A组件传进来的 props

            // 组件将要接收到新的传进的参数钩子
            componentWillReceiveProps(props) {
                console.log('B---componentWillReceiveProps')
            }

保存代码,刷新一下,理论上一刷新,A组件就向B组件传递 props 数据了吧?所以应该在B组件渲染,我们不需要点击的时候 componentWillReceiveProps 生命周期直接执行对吧,我们刷新看效果:

在这里插入图片描述 诶,刷新之后看控制台打印,B组件的 render 钩子执行了,但是 componentWillReceiveProps 没有执行对吧,好的,记住一点,componentWillReceiveProps 生命周期函数,在第一次时候,无效! 所以说我们想触发怎么办?对,点击A组件的按钮,修改 state 状态。

在这里插入图片描述 OK,我们点击按钮之后,钩子触发了,获取并且打印出了传进来的 props,并且重新渲染了。

剩下的几个钩子 shouldComponentUpdate 组件是否应该被更新componentWillUpdate 组件将要被更新render 组件渲染componentDidUpdate 组件更新完成 和之前是一样的用法,这里就不再重复赘述了哈。

就这样。关于旧版本生命周期钩子,就说完了,代码呢,想要全部的话,可以去我的 gitee 看一下。下面一部分,就开始说 新版的生命周期钩子。

【本部分相关代码资料】:我是𝒆𝒅. 的 gitee

旧版本生命周期钩子总结

在这里插入图片描述

  1. 初始化阶段:是由 ReactDOM.render() 触发 -- 初次渲染 - construtor() - componentWillMount() - render() - componentDidMount()
  2. 更新阶段:是由 this.setState() 或者父组件重新 render 触发 - shouldComponentUpdate() - componentWillUpdate() - render() - componentDidUpdate()
  3. 卸载组件:由 ReactDOM.unmountComponentAtNode() 触发 - componentWillUnmount()

尽管哈,前前后后涉及到了很多钩子,但是稍作了解就可以,因为在实际开发过程中,有的钩子基本很少使用到,主要专注一下 componentDidMountrendercomponentWillUnmount 这三个钩子,这三个,是开发过程中经常使用的,其他的知道,需要的时候用,一般不会用到。

新版本生命周期函数

16版本之前,都是使用的旧版本的生命周期,但是从 17 版本开始,就是使用新的生命周期钩子了,大部分一样,只不过是删除了旧版本的三个钩子,新增加了两个钩子

我们先看一下新版本钩子挂载流程图

在这里插入图片描述

如果引入的 js 文件是我的 gitee 仓库里面的 js 文件,那么之前写的就是 16 版本 React 开发的。学习新的生命周期钩子,需要使用 17 版本及以上的。需要重新下载,当然我也在 gitee 里面上传了。

自己怎么下载呢?

在这里插入图片描述

为啥要 React 会有新版和旧版生命周期钩子的区别呢?

因为他们在憋大招!他想加一个异步渲染的功能,但是现在还没加上哈。我们看官方文档。

在这里插入图片描述 上面截图主要关注 新版本的生命周期,componentWillMountcomponentWillReceivePropscomponentWillUpdate 不安全,加了一个前缀 UNSAFE_。在看一段:

在这里插入图片描述 他说17版本已经不支持这三个生命周期了,必须添加 UNSAFE_ 前缀。

所以说新版本的生命周期我们将使用 17 版本。

但是有一件事情我想说一下哈,就是我们用了 17 版本,发现这三个老的钩子还是可以正常使用的哈,就是会弹出一个警告,告诉你要加上前缀,但是不影响执行。再告诉大家一件事,其实 18 版本也出了,还是这几句话,也是说不让用必须加前缀,但是实际使用一下,不加也可以哈。所以说研发团队为了实现一个异步渲染功能,引入了一个新版的生命周期,但是这个大招三年了,啥也没憋出来,除了告诉我们要做,其他啥也没做。

然后我们引入 17 版本的 js 文件。我 gitee 文件夹下面有一个 js2 这里面的是 17版本, js 文件夹下面是 16 版本的,我们修改的话,值修改 react 和 react-dom 两个 js 就可以啊。

在这里插入图片描述 就是换着两个

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js2/react.development.js"></script>
    <!-- 引入react-dom 用于支持 react 操作 dom -->
    <script type="text/javascript" src="../js2/react-dom.development.js"></script>

还完之后,就是 17 版本的 react 了。

OK,我们找到最开始的一个案例。

在这里插入图片描述 这里面有两个生命周期 是 componentWillMount 组件即将挂载componentWillUpdate 组件即将更新、 然后 componentWillReceiveProps 这个组件这个案例里面没有,但是和前两个效果一样的,我们就只看前两个吧。

我们现在不加 UNSAFE_ 前缀,看一下效果。一刷新,控制台报警告了。

在这里插入图片描述 警告就是让你加上前缀,但是我们看到哈,componentWillMount 生命周期钩子其实是执行了的。

所以说不加前缀暂时看,还是可以正常运行的。但是为了正规,我们加上前缀吧。

            // 组件将要挂载的钩子
            UNSAFE_componentWillMount() {
                console.log('Count-componentWillMount')
            }
            // 组件将要被更新
            UNSAFE_componentWillUpdate() {
                console.log("Count-componentWillUpdate")
            }

保存刷新:

在这里插入图片描述 一切正常,就这么简单。

所以说哈,在最开始我说了

新版本的生命周期只不过是删除了旧版本的三个钩子,新增加了两个钩子

其实也不能说是删除了三个旧版本的钩子,人家只是加了个前缀是吧?理解成删除也可以吧。

加了前缀,作用是没有变得,还有和老版本的功能、作用、用法一模一样。

除了删除三个旧版本的钩子,还加了两个钩子,新加的两个钩子不好理解,但是没关系,一般用不到。

新增加钩子:

  • getDerivedStateFromProps() 得到一个派生的状态从props中
  • getSnapshotBeforeUpdate() 在更新之前获取快照

我们一个一个来看。

getDerivedStateFromProps()

得到一个派生的状态从props中。 这是啥意思呢?先写一下吧。注意这个钩子需要使用 static 修饰,不加会报错,并且控制台告诉你需要加。

            // 得到一个派生的状态从props中
            static getDerivedStateFromProps(props, state) {
                console.log('Count-getDerivedStateFromProps')
            }

保存刷新一下。

在这里插入图片描述 报错了,他说啊,需要返回一个 状态 对象,现在返回的是 undefined。那我们先返回一个 null 呗。

            // 得到一个派生的状态从props中
            static getDerivedStateFromProps(props, state) {
                console.log('Count-getDerivedStateFromProps')
                return null
            }

刷新:

在这里插入图片描述

正常了。

好哈,我们现在直接说一下这个生命周期哈,其实啊,这个生命周期名字就是 得到一个派生的状态从props中 。他说是从 props 中,所以说这个钩子可以接受一个参数,就是 props。这个 props 是啥,是传递给组件的数据。比如传进一个 name:

ReactDOM.render(<Count name="我是ed." />, document.getElementById("app"))

我们打印一下这个 props 回调参数

			static getDerivedStateFromProps(props) {
                console.log('Count-getDerivedStateFromProps', props)
                return null
            }

看一下结果:

在这里插入图片描述

获取到 props 了吧?你看获取到的这个值像是啥?像不像一个 状态数据 state ?其实他可以在获取一个参数,就是状态数据 state

			static getDerivedStateFromProps(props, state) {
                console.log('Count-getDerivedStateFromProps', props, state)
                return null
            }

再次打印一下:

在这里插入图片描述

然后他又说 得到一个派生的状态 ,这个派生的状态不就是 return 的东西吗?

我们在组件有一个 count 数据,点击 +1 按钮数字自增,假设我们这边直接返回一个同名的 count 呢?

            static getDerivedStateFromProps(props, state) {
                console.log('Count-getDerivedStateFromProps', props, state)
                return {count: 10}
            }

保存看效果:

在这里插入图片描述 我们看效果哈,就是我返回的派生状态会把自己本身的给替换掉吧,然后我们修改这个 state ,发现页面不渲染了是吧?

总结一下:getDerivedStateFromProps() 钩子 使用状态极低,了解即可,返回状态不可修改。若 state的值在任何时候都取决于props的话,那么可以使用。

官方不建议我们使用,除非很刁钻的情境下使用。看官方说的:

在这里插入图片描述

getSnapshotBeforeUpdate()

另一个新的钩子是啥呢? getSnapshotBeforeUpdate,在更新之前获取快照。

怎么使用呢?很简单,先不管,直接写一个,这个不需要加 static 修饰。

// 在更新之前获取快照
getSnapshotBeforeUpdate() {
    console.log('Count-getSnapshotBeforeUpdate')
}

保存刷新,点击 +1 按钮修改数据更新页面 看一下效果啦:

在这里插入图片描述 报错了,报的啥呢,他说需要返回一个 快照,不能不返回。啥是快照呢?其实啥都可以,比如我们随便返回一个数据。

            // 在更新之前获取快照
            getSnapshotBeforeUpdate() {
                console.log('Count-getSnapshotBeforeUpdate')
                return '我是ed.同学'
            }

返回了一个字符串,这个字符串就可以叫做快照。

在这里插入图片描述 这样就不再报错了。哪有啥用呢?他可以和另一个生命周期配合使用。那个周期呢?componentDidUpdate 组件更新完成周期。这个周期啊,其实可以接受三个参数。我们修改一下这个周期,然后看一下这三个参数都是啥

            // 组件更新完成
            componentDidUpdate(preProps, preState, SnapshotValue) {
                console.log("Count-componentDidUpdate",preProps, preState, SnapshotValue)
            }

保存刷新,点击看控制台打印的数据。

在这里插入图片描述 第一个是 数据更新前的props,第二个是 数据更新前的state,第三个是我们返回的那个快照值

OK,那这有啥用呢?看官网怎么解释的:

在这里插入图片描述

本来想写一个案例的,但是我太懒了,不想写了,因为新增的这两个钩子一般用不到,很难用到,知道就行,但是快照这个钩子,比第一个稍微稍微有用那么一点点。记住就好了。

新版生命周期钩子函数总结

在这里插入图片描述

  1. 初始化阶段:是由 ReactDOM.render() 触发 -- 初次渲染 - construtor() - getDerivedStateFromProps() - render() - componentDidMount()
  2. 更新阶段:是由组件内部 this.setState() 或者父组件重新 render 触发 - getDerivedStateFromProps() - shouldComponentUpdate() - render() - getSnapshotBeforeUpdate() - componentDidUpdate()
  3. 卸载组件:由 ReactDOM.unmountComponentAtNode() 触发 - componentWillUnmount()

【本部分相关代码资料】:我是𝒆𝒅. 的 gitee

好的,本篇博文关于声明周期的内容就到这里了,谢谢各位赏脸划到这里。

这篇博文写的时间很久,谢谢赏光、

拜了个拜!