react hooks useState值为什么没有生效?
今天在工作中遇到一个react hooks问题,虽然解决了但是对于其中的原因不太理解,这里发出来和大家一起讨论一下。具体代码如下,场景步骤如下:
- 点击一次,执行running后,isPolling设为true,并触发polling的useEffect
- 快速再点击一次,执行running,因为running前执行了cancle,所以这时候running内的isPolling应该是false,但实际还是true
看了一些批量更新的知识,好像解释不了这种现象。大家有什么看法吗?
import { useCallback, useEffect, useState } from "react";
export default function MyApp() {
const [isPolling, setIsPolling] = useState(false);
const [pollingCount, setPollingCount] = useState(0);
const [timer, setTimer] = useState();
const handleClick = () => {
cancle();
running();
};
useEffect(() => {
if (isPolling && pollingCount <= 3) {
console.log("33");
clearTimeout(timer);
setTimer(
setTimeout(() => {
console.log("44");
running();
}, 1000)
);
}
}, [isPolling, pollingCount]);
const running = useCallback(() => {
console.log("running11:", isPolling, pollingCount);
if (!isPolling) {
console.log("11");
setIsPolling(true);
} else if (isPolling) {
console.log("22");
setPollingCount(pollingCount + 1);
}
}, [isPolling, pollingCount]);
const cancle = () => {
setIsPolling(false);
setPollingCount(0);
};
return (
<div>
<div onClick={handleClick}>点击</div>
</div>
);
}
执行结果如下
回复
1个回答
test
2024-06-25
其实这个问题很基础,甚至还不涉及到任何框架,这里我用最简单的模型来简化一下你这个问题
const [isPolling, setIsPolling] = useState(true);
const handleClick = () => {
setIsPolling(false)
console.log(isPolling); // true
};
isPolling
是一个常量,在同一个作用域内,无论使用什么方式,都不可能实现后续去改变它的值,这就回答了你的疑问,为什么调用 setIsPolling(false)
后,isPolling
的值还是 true
其实每次更新 useState
定义的状态,都会驱动 函数组件
重新执行,在重新执行的作用域中,isPolling
的值才是更新后的值,
那么在更新之前的上一次作用域中如何确保拿到更新后的值呢,React也提供了相应的方式,使用 setter
的回调
setIsPolling((prevIsPolling) => {
console.log(isPolling); // false
})
React内部会在组件对应的 fiber
结构上维护一个更新队列,对于同一个状态连续的 setState 调用会形成一个循环链表,将上一次 setState 的结果传递给下一个 setState 的回调,因此通过回调的方式你能拿到上一次 setIsPolling
的新值
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容