我正在尝试使用 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
/>
);
我希望 muffinSettings.isOrdered 在 setMuffinSettings 调用之前为 FALSE,之后为 TRUE,前提是 muffinSettings.isInStock 是 TRUE(确实如此)。
使用我现在拥有的代码,松饼设置落后了一步。在下面的handleMuffinOrder的代码片段中,我包含了第一次单击按钮时打印的控制台输出。但是,第二次单击它时,isOrdered BEFORE的值已设置为TRUE。因此,似乎isOrder的值在第一次和第二次按钮单击之间发生了变化。
我相信这不是建议的"setState 不会立即更新状态"问题的重复,因为我们在这里使用的是 React Hooks,它仅在 React 16.8 之后可用,而不是"较旧"的 React 状态系统。根据 React 文档,setMuffinSettings 接受的唯一参数是新状态,即新对象;它不会像上面建议的问题的答案所建议的那样进行回调。
它本身并不落后一步,它比这更微妙 - 出于性能原因,状态更新是批处理的,并且异步发生。如果你需要在状态改变后做某事,那么useEffect
就是你的朋友。
即使在钩子中,setState
的基本实现也保持不变。它仍然是异步的。
再次引用文档:
状态更新可能是异步的。不应依赖它们的值来计算下一个状态。
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>;
};
对于如此简单的组件,这是最简单的方法。我在代码沙盒中测试过,它将状态更改为 true