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

相关推荐
独立开阀者_FwtCoder几秒前
手握两大前端框架,Vercel 再出手拿下 Nuxt.js,对前端有什么影响?
前端·javascript·vue.js
独立开阀者_FwtCoder几秒前
弃用 html2canvas!快 93 倍的截图神器!
前端·javascript·vue.js
weixin_3993806915 分钟前
TongWeb8.0.9.0.3部署后端应用,前端访问后端报405(by sy+lqw)
前端
伍哥的传说36 分钟前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript
洛小豆1 小时前
深入理解Pinia:Options API vs Composition API两种Store定义方式完全指南
前端·javascript·vue.js
洛小豆1 小时前
JavaScript 对象属性访问的那些坑:她问我为什么用 result.id 而不是 result['id']?我说我不知道...
前端·javascript·vue.js
叹一曲当时只道是寻常1 小时前
Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
前端·golang
超级土豆粉1 小时前
npm 包 scheduler 介绍
前端·npm·node.js
bug爱好者1 小时前
原生小程序如何实现跨页面传值
前端·javascript
随笔记1 小时前
uniapp开发的小程序输入框在ios自动填充密码,如何欺骗苹果手机不让自动填充
前端·ios·app