这是我的代码:
function Tiker() {
var [count, setCount] = useState(0);
useEffect(() => {
var timerID = setInterval(_=>
setCount(count=>count+1)//setCount(count+1) wont work
, 1000);
return function cleanup() {
clearInterval(timerID);
};
}, []);
return <div>
this is ticker
<button onClick={() =>
setCount(count + 1)//setCount(count+1) does work
}>up </button>
{count}
</div>
}
通过反复试验,我发现如果我从setinterval回调中使用setCount,则必须将回调传递给set状态,而不仅仅是传递值。
如果我通过onclick致电,情况并非如此。
那是为什么?
答案 0 :(得分:2)
问题是useEffect
的第二个参数
useEffect(() => {
var timerID = setInterval(_=>
setCount(count=>count+1)//setCount(count+1) wont work
, 1000);
return function cleanup() {
clearInterval(timerID);
};
}, []);
它是空数组([]
)。它为钩子定义了list of dependencies。因为它为空,这意味着钩子不依赖于任何状态或道具的值。因此,count
变量在第一次调用useEffect
时就被消耗掉了,而且保持陈旧状态。
要解决此问题,您应该完全删除useEffect
的第二个参数,或者使数组包含[count]
。
回调正在工作,因为它接收先前的计数值作为第一个参数。
所以正确的代码看起来像
function Tiker() {
var [count, setCount] = useState(0);
useEffect(() => {
var timerID = setInterval(_=>
setCount(count + 1)
, 1000);
return function cleanup() {
clearInterval(timerID);
};
}, [count]); // Put variable that useHook depends on
return <div>
this is ticker
<button onClick={() =>
setCount(count + 1) //setCount(count+1) does work
}>up </button>
{count}
</div>
}
答案 1 :(得分:0)
从setInterval调用时,使用回调似乎是更改状态的最简单方法。正如Frodor的上述评论和https://overreacted.io/making-setinterval-declarative-with-react-hooks/
所表明的那样