为什么这不能像正常的一秒钟计数器一样工作?
function UseEffectBugCounter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const intervalId = setInterval(() => {
setCount(count + 1);
console.log(count);
}, 1000);
return () => clearInterval(intervalId);
}, []);
return <div>The count is: {count}</div>;
}
示例:https://codesandbox.io/s/sparkling-rgb-6ebcp
-是因为过时的关闭吗?
或
-是因为计数是状态变量,并且在状态更新后将重新渲染组件,所以将创建一个新的间隔来创建某种循环吗?
或
-还有其他东西吗?
我正在寻找一个为什么可能在此答案中出现的原因,有几篇不同的文章说明了为什么它不起作用(如上所述)。但是到目前为止,没有人能够提供一个很好的论据。
答案 0 :(得分:2)
您可以将回调用于设置状态以使用最新的计数器值:
setCount(count => (count + 1));
答案 1 :(得分:0)
您可能需要在count
中添加对useEffect
的依赖性。当前useEffect
仅在安装上被调用,此后不被调用(即当计数值更改时)。
因此它总是说0
,因为useEffect
仅执行一次(在mount上),而此时计数值设置为0
。因此,由于关闭,它每次在setInterval
上记录为0。
我已经更新了代码沙箱以查找原因和有意义的日志。这是沙盒链接:https://codesandbox.io/s/admiring-thompson-uz2xe
如何查找闭合值:您可以检查日志并遍历原型对象以找到[[Scopes]]
,并将获得以下屏幕快照中所示的值:
这将起作用:
React.useEffect(() => {
const intervalId = setInterval(() => {
setCount(count + 1);
console.log(count);
}, 1000);
return () => clearInterval(intervalId);
}, [count]);
您可以查看以下文档:https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
您也可以阅读:https://overreacted.io/making-setinterval-declarative-with-react-hooks/
希望这会有所帮助!
答案 2 :(得分:0)
如果您删除了第二个参数供useEffect使用,则您的状态会发生变化,但始终会呈现您的应用程序,但这是一种不好的做法。您需要在第二个参数中选择需要观看的参数...
具有选定参数的示例:
React.useEffect(() => {
const intervalId = setInterval(() => {
setCount(count + 1);
console.log(count);
}, 1000);
return () => clearInterval(intervalId);
}[count]);
无
React.useEffect(() => {
const intervalId = setInterval(() => {
setCount(count + 1);
console.log(count);
}, 1000);
return () => clearInterval(intervalId);
});
答案 3 :(得分:0)
因为您没有添加count
来使用Effect的依赖关系,所以效果数内部始终为0
。
您应该使用useReducer
来解决问题:
function UseEffectBugCounter() {
const [count, dispatchCount] = React.useReducer((state, { type }) => {
switch(type) {
case 'inc':
return state + 1
default:
return state
}
}, 0);
React.useEffect(() => {
const intervalId = setInterval(() => {
dispatchCount({ type: 'inc'})
}, 1000);
return () => clearInterval(intervalId);
}, []);
return <div>The count is: {count}</div>;
}
答案 4 :(得分:0)
您需要传递计数而不是useEffect
function UseEffectBugCounter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const intervalId = setInterval(() => {
setCount(count + 1);
console.log(count);
}, 1000);
return () => clearInterval(intervalId);
},[count]);
return <div>The count is: {count}</div>;
}