更新的状态值不会在反应中的函数内部更新
Posted
技术标签:
【中文标题】更新的状态值不会在反应中的函数内部更新【英文标题】:updated state value are not updated inside function in react 【发布时间】:2021-10-06 12:06:15 【问题描述】:react state 更新的值显示在 use Effect 但内部函数只显示一个旧值。
const [counter, setCounter] = useState(0);
我正在尝试更新设置间隔函数内的计数器值
const handleIncrease = () =>
clearInterval(intervalval);
if (counter < 10)
let increment = setInterval(() =>
console.log("isCounterContinue@handleIncrease", counter);
setCounter((prev) => prev + 1);
, 1000);
setIntervalval(increment);
; 显示内部 useEffect 更新的值。但内部函数handleIncrease 只显示旧值 基本上,我正在尝试做计数器值超过 30 时不会增加。
代码链接:https://codesandbox.io/s/bold-cdn-zzbs2?file=/src/App.js
【问题讨论】:
这能回答你的问题吗? State not updating when using React state hook within setInterval 您的代码箱中的代码似乎可以按照您描述的方式运行...但它也与您在此处共享的 sn-p 不匹配。有什么问题? handleIncrease 函数内的计数器值未更新。因此,如果我尝试添加条件(基于计数器状态),则不会在 handleIncrease 函数中应用handleIncrease
仅在单击按钮时调用,具有当前状态。点击处理程序中有什么要更新的?我认为您真正追求的是在间隔的回调中访问更新的counter
状态,该状态每秒“滴答”一次。
在更新计数器状态后每 1000 毫秒在点击处理程序中。但它没有在 handleIncrease 函数中显示更新的值。我很困惑里面 useEffect 更新的值被显示,但里面的 handleIncrease 计数器值没有显示
【参考方案1】:
handleIncrease
仅在单击按钮时调用,具有当前状态。在点击处理程序中没有什么要更新的。我认为您真正想要的是访问间隔回调中更新的counter
状态,该回调每秒“滴答”一次。或者更准确地说,响应 isCounterContinue
状态切换 false 以在达到限制时停止间隔。
使用 ref 来保存对间隔计时器的引用,并使用它来设置/清除,而不是在外壳中过时的状态。
const Timer = () =>
const [counter, setCounter] = useState(0);
const intervalRef = useRef();
useEffect(() =>
console.log( counter );
if (counter >= 5)
clearInterval(intervalRef.current);
, [counter]);
const handleIncrease = () =>
clearInterval(intervalRef.current);
intervalRef.current = setInterval(() =>
setCounter((prev) => prev + 1);
, 1000);
;
const handleDecrease = () =>
clearInterval(intervalRef.current);
intervalRef.current = setInterval(() =>
setCounter((prev) => prev - 1);
, 1000);
;
const handleStop = () =>
clearInterval(intervalRef.current);
;
return (
<>
<div>counter</div>
<div>
<button onClick=handleDecrease>Decrease</button>
<button onClick=handleStop>Stop</button>
<button onClick=handleIncrease>Increase</button>
</div>
</>
);
;
建议
递增/递减处理程序除了添加到计数之外基本相同。使用 curried 函数通过关闭递增值来处理这两种情况。由于“停止”处理程序共享逻辑来清除间隔,因此使用 0
是一个虚假值这一事实,并且只为真实(即非零)数值重新启动间隔计时器,并对所有三个按钮使用一个处理程序。
const handleIncrease = (val) => () =>
clearInterval(intervalRef.current);
if (val)
intervalRef.current = setInterval(() =>
setCounter((prev) => prev + val);
, 1000);
;
...
<button onClick=handleIncrease(-1)>Decrease</button>
<button onClick=handleIncrease(0)>Stop</button>
<button onClick=handleIncrease(1)>Increase</button>
【讨论】:
它正在工作,你能解释一下为什么没有 Ref,handleIncrease 函数中不显示更新值的原因。 @ShatishDesai 仅在单击时显示当前的counter
值,而不是在间隔“滴答”时显示。如果您继续每秒单击“增加”按钮,您将看到更新的counter
状态。如果您等待几秒钟并然后再次单击“增加”,您将看到当前的counter
状态。以上是关于更新的状态值不会在反应中的函数内部更新的主要内容,如果未能解决你的问题,请参考以下文章