useState的执行流程和useEffect

1.useState的执行流程

javascript 复制代码
import React from 'react'
export default function App() {
    console.log('App组件重新渲染');
    const [count, setCount] = React.useState(0)
     setCount(0)
    return (
        <div>
            {count}
            <button>点为</button>
        </div>
    )
}

当我们直接在函数组件直接使用更新state方法去更新这个count值,我们运行这个代码会发生什么呢?

​编辑

竟然调用了52次!!!而且因为太多次重新渲染被限制终止了。我在之前用useState的时候,我知道里面有2个返回值,有数组解构的方式获取。然后前面是我存的state值。后面就是更新state的方法,而且这个方法在使用的时候会自动重新渲染(会进行对比,如果和当前的虚拟DOM不同的话执行重新渲染,但是如果相同的话就不会渲染),我是这么去做的,也是这么去理解的,但是上面的情况就很奇怪,为什么没有去对比在判断是不是去渲染,这时候就要去思考这个useState到底是怎么执行的。

当我们在函数体中直接调用setState时就会触发上述错误,之前理解的新的state值和旧值一样的时候,不会出发组件重新渲染,setState()的执行流程,当我们调用setCount()-->dispatchSetDate()--->会判断当前组件处于什么状态---》渲染阶段和非渲染阶段

1.渲染阶段--》不会检查state值是否相同

2.非渲染阶段--->会检查state值是否相同

不同则重新渲染组件 相同就不会重新渲染

如果值相同,React会在一些情况下继续执行组件渲染,但是这个渲染不会出发其子组件的渲染,这次渲染不会产生实际的效果,这种情况发生在值第一次相同时。

也就是说当我们组件第一次加载完之前,我们是不可以去直接调用set方法更新state的,因为不会检查是否相同,永远都认为是最新值,导致无限重新渲染。我们就需要在非渲染阶段,也就是组件加载完毕渲染到页面上之后,我们去调用更新state,才可以进行对比然后去渲染。

scss 复制代码
  setTimeout(() => {
        setCount(1)
    }, 0)

​编辑

所以我们只需要用这种方法,让他在渲染阶段不执行,或者放到函数里面,在调用的时候执行,而不是渲染阶段执行就可以了。不过我们可以用useEffect去规避这种情况。下面就来说说这个钩子。

这里渲染三次第三次实际上是我的插件React Tool帮我去调用的渲染,这个开发工具会展示虚拟Diff重绘,即使实际没有改变。严格模式也会这样,为了排除副作用代码。

2.useEffect的介绍

首先先拆开来看,Effect副作用?什么是副作用。就是我们上面直接在渲染阶段写了更新state的方法,导致无限循环影响组件的渲染,那么我们需要一个东西去帮我们跳过渲染阶段,或者说给一些逻辑定义什么时候执行。也就是说这个钩子是一个副作用容器,控制里面的代码什么时候执行,执行几次。

那么上面的定时器我们就可以丢掉了。

javascript 复制代码
import React from 'react'

export default function App() {
    console.log('App组件重新渲染');

    const [count, setCount] = React.useState(0)
    //useEffect()是一个钩子函数需要一个函数作为参数
    //这个作为参数的函数,将会在组件渲染完毕后执行
    React.useEffect(() => {
        setCount(1)
    }, [count])
    const handle = () => {
        console.log('点击按钮');
        setCount(1)
    }
    //点击按钮第一次初始值是0 点击按钮变为count --->1
    //  App组件重新渲染了 执行了
    //第二次点击按钮 count--->1
    // App组件重新渲染了执行了
    //第三次点击 count-->1
    //App组件重新渲染了 没有执行
    return (
        <div>
            {count}
            <button onClick={handle}>点为</button>

        </div>
    )
}

来介绍一下这个钩子,首先里面的参数是一个函数,然后后面的数组是一个依赖项,比如这里我们写了count这个state,他就会监听count是否改变,如果改变了就重新调用一下,确保里面如果用到count的话是最新的值,如果为【】空数组,那么就是渲染阶段完毕之后,执行一次。这样跟定时器的效果相同。

​编辑

也是调用的时候渲染一次,仅此而已。我们添加点击事件,就会根据Diff判断。

​编辑

点很多次也不会重新渲染,因为对比虚拟DOM没有变化。这样我们就知道这个钩子函数怎么用了。当然只是知道怎么用,只有开发的时候用到才能真正的说会用。

相关推荐
Mintopia4 小时前
🌐 数据合规框架下的 WebAIGC 训练数据处理技术规范
前端·javascript·aigc
骥龙4 小时前
2.6、Web漏洞挖掘实战(下):XSS、文件上传与逻辑漏洞深度解析
前端·xss
用户433845375694 小时前
Promise深度解析,以及简易版的手写实现
前端
梦之云4 小时前
state 状态相关
前端
梦之云4 小时前
effect 副作用相关
前端
golang学习记4 小时前
从0死磕全栈之Next.js 生产环境优化最佳实践
前端
Mintopia5 小时前
🧠 Next.js 还是 Nuxt.js?——当 JavaScript 碰上命运的分叉路
前端·后端·全栈
5pace5 小时前
Mac Nginx安装、启动、简单命令(苍穹外卖、黑马点评前端环境搭建)
java·前端·nginx·macos·tomcat
Learn Beyond Limits5 小时前
如何在Mac进行Safari网页长截图?
前端·macos·safari·方法·操作·功能·开发者平台
阿珊和她的猫5 小时前
深入剖析 Vue Router History 路由刷新页面 404 问题:原因与解决之道
前端·javascript·vue.js