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