为什么我需要 setTimeout 来更新 React 组件中的状态

Why do I need setTimeout to update state in React component

为什么我需要在我的 React 组件中用 setTimeout 包装我的 setValue?

这个有效

<Button onClick={() => acceptOne()}>
  set value with setTimeout
</Button>

const acceptOne = () => {
  setTimeout(() => {
    setEditMode(false);
  });
};

这不...

<Button onClick={() => acceptTwo()}>
  set value without setTimeout
</Button>

const acceptTwo = () => {
  setEditMode(false);
};

这里有一个 CodeSandbox example 完整代码来演示这个问题。

我是 React 的新手,已经不得不使用 setTimout 来让状态像这样改变。我觉得这很可能是初学者的事情,还有一些我还不了解的 React 特定内容。这是怎么回事,为什么我不使用 setTimeout 时 setValue 不起作用?

问题出在您代码的第一行 <div onClick={() => setEditMode(true)}>

查看更新后的代码段 - https://codesandbox.io/s/charming-http-b637o

Jai 在他的回答中很好地解释了逻辑。

这是由于事件传播而发生的。如您所见,您已将一个事件绑定到父级 div。因此,每当您 单击 按钮时,父 div 的 事件也会执行

Why it works with setTimeout?

因为它在div的事件之后执行,因为它被推送到其他异步进程并且需要时间来执行。

您可以添加 event.stopPropagation() 以阻止事件在 DOM 中冒泡:

  const acceptOne = e => {
    e.stopPropagation();
    setEditMode(!editMode);
  };

  const acceptTwo = e => {
    e.stopPropagation();
    setEditMode(!editMode);
  };

现在将事件更改为:

onClick={acceptOne}
onClick={acceptTwo}

或:

onClick={e => acceptOne(e)}
onClick={e => acceptTwo(e)}  

Updated codesandbox

  <div onClick={() => setEditMode(true)}>

这是你的问题。包装您的按钮事件的父 DIV 被调用以及您的按钮点击。 setTimeout 提供的延迟允许它在父 div 之后进入,因此有效。您可以重组 HTML 或做一些事件 stopPropogation 的事情来处理它。

https://codesandbox.io/s/charming-ganguly-mg4zx 我修好了,有 link。 所以这是因为在第二次点击输入后它运行父 div 也点击因为这个输入包装到 div 元素中, <div onClick={() => setEditMode(!editMode)}> 因此,当您将 setTimeout 放在那里时,第二个输入点击在父 div 元素点击功能之前运行,这就是它起作用的原因。这与javascript事件循环有关,观看有关事件循环的视频,您将了解那里发生的事情 https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=54s