Javascript setTimeout和状态集函数之间的奇怪交互

Javascript setTimeout和状态集函数之间的奇怪交互,javascript,reactjs,Javascript,Reactjs,给定此代码段: const [filled, setFilled] = useState(0); //... useEffect(() => { console.log("start"); setFilled(() => { setTimeout(() => { console.log("old1"); setFilled(() => { setTime

给定此代码段:

const [filled, setFilled] = useState(0);
//...
useEffect(() => {
    console.log("start");
    setFilled(() => {
      setTimeout(() => {
        console.log("old1");
        setFilled(() => {
          setTimeout(() => {
            console.log("old2");
          }, 1000);
          return 20;
        });
        console.log("old3");
      }, 1000);
      return 10;
    });
  }, []);
有人能解释为什么old2打印两次吗? 我知道代码很奇怪,但我还是不知道。它必须与函数状态集函数的内部反应处理有关,但我在文档中找不到任何解释


谢谢。

两个
setTimeout()
setFilled()
都是异步执行的。我们无法确定结果何时被重新调整,这就是为什么您会有这种行为。

您违反了React提供的接口契约。
setState()
updater函数必须是纯函数,即没有副作用

之所以需要这样做,是因为React不保证何时调用更新程序函数,也不保证调用更新程序函数的次数


即使您认为您已经确定了这种情况下的具体行为,它可能会在下一个版本中更改,而不会引起任何通知,因此,甚至不要试图依赖您可以从这个“奇怪”代码中观察到的内容。

“我有一些奇怪的代码,我不知道它是做什么的,但它会做一些奇怪的事情。”-听起来像是X/Y问题,这只是递归setTimeout的简化版本,所以没那么奇怪。你想用这个实现什么?@ksav,在这种情况下,我试图每秒执行一次特定的操作-console.log。这段代码唯一缺少的是递归setTimeout,它在每次迭代时将动作加倍,这意味着它将打印old2 4、8、16次等等。所以你试图每秒设置一次状态?请参阅并考虑编辑您的问题。