我在这里有这段代码:
export default function App() {
const [count, setCount] = useState(0);
const [step, setStep] = useState(0);
const reff = useRef(0);
useEffect(() => {
const id = setInterval(() => {
setCount((c) => {
console.log({ step }, "reff.current before incr ", reff.current);
reff.current = reff.current + step;
console.log("ref.curret after incr ", reff.current);
return c + step;
});
}, 6000);
return () => clearInterval(id);
}, [step]);
return (
<>
<h1>Count:{count}</h1>
<h1>Step: {step}</h1>
<input
type="button"
onClick={(e) => setStep((prevStep) =>(prevStep + 1))}
value="+ step"
/>
</>
);
}
您可以在这里查看:https://codesandbox.io/s/gracious-roentgen-31ntb?file=/src/App.js:0-817请注意,我正在增加
setCount
内的 ref回调当组件加载一个 setInterval 时启动。如果我通过递增步骤 再次触发 useEffect在 6 秒过去前 ,它清除 setInterval 并创建一个新的。
现在,如果我不再增加 step 并等待 6 秒,我会看到
step: 1 reff.current before incr, 0
第一次调用 setInterval 回调。在下一行(
reff.current = reff.current + step
)递增后,我看到 "ref.curret after incr ", 1
当 6 秒后再次调用 setInterval 回调时,我看到了step: 1 reff.current before incr, 2 //how did this become 2
我不明白 reff.current
的值如何是 2。这只发生在我增加步骤(清除第一个间隔)时。如果我将初始步长设置为 1 并且不增加它,我会看到预期值。 .刚刚又查了。它没有按预期工作。
我不明白为什么
reff.current
的值第二次调用 setInterval 回调时为 2。转到沙盒链接,然后
log 1:{step: 1} "reff.current before incr "0
log 2: ref.curret after incr 1
//second time callback is called
log 3: {step: 1} "reff.current before incr "2 //this should be 1
log 4: ref.curret after incr 3```
最佳答案
出现问题是因为您在传递给 reff.current
的更新程序函数中执行了副作用(更新 setCount
) .
测试版 react docs比如说:
Updater functions run during rendering, so updater functions must be pure and only return the result. Don’t try to set state from inside of them or run other side effects. In Strict Mode, React will run each updater function twice (but discard the second result) to help you find mistakes.
您正在
StrictMode
中运行您的应用程序.要验证它,请评论它:const rootElement = document.getElementById('root');
ReactDOM.render(
// <StrictMode>
<App />,
// </StrictMode>,
rootElement
);
并且问题不再发生。
关于javascript - 为什么 ref 值增加两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70458370/