javascript - 为什么 ref 值增加两次

标签 javascript reactjs

我在这里有这段代码:

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/

    相关文章:

    javascript - 你如何强制 Node 模块的绝对路径?

    javascript - 无法删除表单中选择框的选项

    reactjs - mapStateToProps 根本没有被调用

    javascript - 按 Shift 键停止 JavaScript 代码

    javascript - Meteor AutoForm 中的唯一字段

    javascript - 如何从子 Prop React 15.5.0 调用父函数

    javascript - 图像中的阴影 React Native

    javascript - 根据环境响应不同的主页最佳实践

    javascript - onClick 事件触发后提交的属性不会更新

    javascript - Angular.js 相当于 `rails generate scaffold` ?