这是我的代码:
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,我必须将回调传回设置状态,而不仅仅是值。
如果我从OnClick打来电话,则不是这种情况。
为什么?
问题是useEffect
useEffect(() => {
var timerID = setInterval(_=>
setCount(count=>count+1)//setCount(count+1) wont work
, 1000);
return function cleanup() {
clearInterval(timerID);
};
}, []);
它是空数组([]
(。它定义了钩子的依赖性列表。因为它为空,这意味着钩子并不取决于状态或道具的任何值。因此,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>
}
看来,使用回调是从setInterval调用状态的最简单方法。在上面和https://overreacted.io/making-setinterval-declarative-with-react-hooks/