使用React Hook setSomeSetting更改组件状态要落后

时间:2019-06-05 20:44:55

标签: javascript reactjs react-hooks

我正在尝试使用React Hooks来管理简单文本输入字段和提交输入按钮的状态。输入字段将持续进行验证(现在仅检查长度是否大于等于1),并且目标是当单击提交按钮且输入有效时,状态对象的“ isOrdered”键的值为TRUE。

我已将setMuffinSettings的参数扩展为显式返回对象,并确认此返回的对象具有isOrdered:true。因此,问题与setMuffinSettings本身有关,而不是传递给setMuffinSettings的不正确对象。

我还研究了其他两个与React Hooks(特别是钩子)有关的StackOverflow问题,这些问题“落后一步”。这些问题的解决方案都不能解决我的问题。

反应挂钩和设置变量初始化:

  const [muffinSettings, setMuffinSettings] = useState({
    isInStock: false,
    isOrdered: false,
  });

提交按钮事件处理程序:

  const handleMuffinOrder = () => {
    console.log(muffinSettings); // BEFORE: isOrdered is correctly false
    if (muffinSettings.isInStock) {
      console.log('reached'); // this is printed so it's not an issue with isInStock
      setMuffinSettings(prev => ({ ...prev, isOrdered: true }));
    }
    console.log(muffinSettings); // AFTER: isOrdered is incorrectly still false
  }

提交按钮:

    return (
      <SubmitOrderButton>
        text="Submit your muffin order"
        // onButtonClick={handleMuffinOrder}
        onButtonClick={() => handleMuffinOrder()}
        // the 2 lines above give me the same error
      />
    );

我希望在setMuffinSettings调用之前muffinSettings.isOrdered为FALSE,然后在TRUE之后(前提是muffinSettings.isInStock为TRUE)。

使用我现在拥有的代码,muffinSettings落后了一步。在下面的handleMuffinOrder的代码段中,我包含了第一次单击该按钮时输出的控制台输出。单击它的 second 次,但是isOrdered BEFORE的值已设置为TRUE。因此,似乎isOrdered的值在第一次和第二次单击之间“改变了”。

我相信这不是建议的“ setState不会立即更新状态”问题的副本,因为我们在这里使用React Hooks,这些仅从React 16.8起可用,而不是“较旧的” React状态系统。根据React文档,setMuffinSettings唯一接受的参数是新状态,即新对象;不需要上述建议的答案所建议的回调。

3 个答案:

答案 0 :(得分:0)

即使是钩子,setState的基本实现也保持不变。它仍然是异步的。

再次从docs报价:

  

状态更新可能是异步的。您不应依靠它们的值来计算下一个状态。

答案 1 :(得分:0)

这不是落后一步,它比那更微妙-出于性能原因,状态更新是分批进行的,并且异步发生。如果您需要在状态改变后 做某事,那么useEffect是您的朋友。

答案 2 :(得分:0)

 const [isInStock, setIsInState] = useState(true);
  const [isOrdered, setIsOrdered] = useState(false);

  const handleMuffinOrder = () => {
    if (isInStock) {
      setIsOrdered(true);
    }
  };
  console.log(isInStock, isOrdered);
  return <button onClick={() => handleMuffinOrder()}> Click Me </button>;
};

这是使用这种简单组件的最简单方法。我在CodeSandbox中进行了测试,它将状态更改为true