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

相关推荐
前端小超超21 分钟前
如何配置capacitor 打包的ios app固定竖屏展示?
前端·ios·web app
nightunderblackcat28 分钟前
新手向:从零理解LTP中文文本处理
前端·javascript·easyui
kyle~30 分钟前
python---PyInstaller(将Python脚本打包为可执行文件)
开发语言·前端·python·qt
User:你的影子36 分钟前
WPF ItemsControl 绑定
开发语言·前端·javascript
会有钱的-_-1 小时前
基于webpack的场景解决
前端·vue.js·webpack·安全性测试
LFly_ice1 小时前
学习React-10-useTransition
前端·学习·react.js
咔咔一顿操作1 小时前
【CSS 3D 交互】实现精美翻牌效果:从原理到实战
前端·css·3d·交互·css3
知识分享小能手2 小时前
React学习教程,从入门到精通,React 构造函数(Constructor)完整语法知识点与案例详解(16)
前端·javascript·学习·react.js·架构·前端框架·vue
召摇2 小时前
Nue.js深度解析:极简主义前端框架的革新实践
前端·node.js
小徐_23332 小时前
uni-app 也能使用 App.vue?wot-starter 是这样实现的!
前端·uni-app