简体   繁体   English

使用React Hook setSomeSetting进行组件状态更改是落后的一步

[英]Component state change with React Hook setSomeSetting is one step behind

I'm trying to use React Hooks to manage state for a simple text input field and a submit input button. 我正在尝试使用React Hooks来管理简单文本输入字段和提交输入按钮的状态。 The input field is continuously validated (right now just checking if length >= 1) and the goal is for the state object's 'isOrdered' key to have a value of TRUE when the submit button is clicked and the input is valid. 输入字段被持续验证(现在只检查长度> = 1),目标是当单击提交按钮并且输入有效时,状态对象的'isOrdered'键的值为TRUE。

I've expanded the argument to setMuffinSettings to explicitly return an object and have confirmed that this returned object has isOrdered: true. 我已经将参数扩展为setMuffinSettings以显式返回一个对象并确认此返回的对象具有isOrdered:true。 So the issue has something to do with the setMuffinSettings itself, not an incorrect object being passed to setMuffinSettings. 所以这个问题与setMuffinSettings本身有关,而不是传递给setMuffinSettings的错误对象。

I've also looked at the two other StackOverflow questions that have to do with React Hooks (specifically hooks) and being 'one step behind.' 我还看了另外两个与React Hooks(特别是钩子)有关的StackOverflow问题,并且“落后一步”。 Neither of these questions' solutions was able to resolve my problem. 这些问题的解决方案都无法解决我的问题。

React hook and settings variable initialization: React钩子和设置变量初始化:

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

Submit button event handler: 提交按钮事件处理程序

  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
  }

Submit button: 提交按钮:

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

I expect muffinSettings.isOrdered to be FALSE before the setMuffinSettings call, and TRUE afterwards, provided that muffinSettings.isInStock is TRUE (which it is). 我希望在setMuffinSettings调用之前,muffinSettings.isOrdered为FALSE,之后为true,前提是muffinSettings.isInStock为TRUE(它是)。

With the code I have right now, muffinSettings is one step behind. 凭借我现在的代码,muffinSettings落后了一步。 In the code snippet for handleMuffinOrder below, I include the console output that's printed the first time you click the button. 在下面的handleMuffinOrder的代码片段中,我包含了第一次单击按钮时打印的控制台输出。 The second time you click it, however, the value for isOrdered BEFORE is already set to TRUE. 但是, 第二次单击它时,isOrdered BEFORE的值已设置为TRUE。 So it seems like the value for isOrdered is changed 'between' the first and second button-clicks. 因此,似乎isOrdered的值在第一次和第二次按钮点击之间“更改”。

I believe this is not a duplicate of the suggested 'setState doesn't update state immediately' question as we are using React Hooks here, which have only been available since React 16.8, and not the 'older' React state system. 我认为这不是建议的'setState不立即更新状态'问题的重复,因为我们在这里使用React Hooks,它们仅在React 16.8之后可用,而不是'旧的'React状态系统。 According to the React docs, the only argument setMuffinSettings would accept is the new state ie the new object; 根据React文档,setMuffinSettings接受的唯一参数是新状态,即新对象; it would not take a callback as the above suggested question's answer recommends. 如上面建议的问题的答案所建议的那样,它不需要回调。

Even in hooks, the fundamental implementation of setState remains the same. 即使在钩子中, setState的基本实现仍然是相同的。 It is still asynchronous. 它仍然是异步的。

Quoting again from the docs : 再次从文档中引用:

State Updates May Be Asynchronous. 状态更新可能是异步的。 You should not rely on their values for calculating the next state. 您不应该依赖它们的值来计算下一个状态。

It isn't one step behind as such, it's more subtle than that - for performance reasons, state updates are batched and happen asynchonously. 它不是落后一步,它比那更微妙 - 出于性能原因,状态更新被批量处理并且异常发生。 If you need to do something after a state changes, then useEffect is your friend. 如果您需要状态更改执行某些操作,那么useEffect就是您的朋友。

 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>;
};

This is the easiest way with such a simple component. 这是使用这么简单的组件的最简单方法。 I tested in CodeSandbox and it changes the state of is ordered to true 我在CodeSandbox中进行了测试,它将命令状态更改为true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM