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

相关推荐
pe7er3 分钟前
使用CDN、ImportMap增强Vue playground
前端
ze_juejin13 分钟前
Angular的懒加载由浅入深
前端
JSON_L14 分钟前
Vue 详情模块 4
前端·javascript·vue.js
码间舞20 分钟前
什么是Tearing?为什么React的并发渲染可能会有Tearing?
前端·react.js
gnip32 分钟前
做个交通信号灯特效
前端·javascript
小小小小宇32 分钟前
Webpack optimization
前端
尝尝你的优乐美34 分钟前
前端查缺补漏系列(二)JS数组及其扩展
前端·javascript·面试
咕噜签名分发可爱多36 分钟前
苹果iOS应用ipa文件安装之前?为什么需要签名?不签名能用么?
前端
她说人狗殊途1 小时前
Ajax笔记
前端·笔记·ajax
yqcoder1 小时前
33. css 如何实现一条 0.5 像素的线
前端·css