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没有变化。这样我们就知道这个钩子函数怎么用了。当然只是知道怎么用,只有开发的时候用到才能真正的说会用。

相关推荐
AI视觉网奇2 小时前
rknn yolo11 推理
前端·人工智能·python
gplitems1232 小时前
Gunslinger – Gun Store & Hunting WordPress Theme: A Responsible
开发语言·前端·javascript
wyzqhhhh5 小时前
less和sass
前端·less·sass
Nan_Shu_6146 小时前
学习:uniapp全栈微信小程序vue3后台-额外/精彩报错篇
前端·学习·微信小程序·小程序·uni-app·notepad++
excel7 小时前
Vue3 中的双向链表依赖管理详解与示例
前端
前端小白从0开始8 小时前
Chrome DevTools高级用法:性能面板内存泄漏排查
前端·chrome·chrome devtools
EveryPossible8 小时前
带有渐变光晕
前端·javascript·css
jojo是只猫8 小时前
Vue 3 开发的 HLS 视频流播放组件+异常处理
前端·javascript·vue.js
卓码软件测评8 小时前
第三方软件登记测试机构:【软件登记测试机构HTML5测试技术】
前端·功能测试·测试工具·html·测试用例·html5
CS Beginner8 小时前
【html】canvas实现一个时钟
前端·html