我正在尝试使用react钩子动态管理一个状态内的多个加载状态。
但是,当我根据api调用的结果(成功或错误)更新状态对象时,它会产生非常奇怪的结果。
如下面的代码示例所示,单击按钮将触发按钮的加载状态为真。
当我在按钮1通话时单击按钮1,然后单击按钮2(在这里我只是用超时进行模拟),它们都按预期顺序将其加载状态设置为true。
然后,一段时间后,两个加载状态都设置为false。
但是,两个通话都结束了,按钮1的加载状态再次设置为true ...!?
我不确定如何解决此问题,感谢您的帮助。 谢谢。
https://codesandbox.io/s/usestate-async-timeout-issue-oknvu
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [loading, setLoading] = useState({});
const handleOnClick = id => {
setLoading({ ...loading, [id]: true });
setTimeout(() => {
// simulate the case for when error is returned after an api call.
setLoading({ ...loading, [id]: false });
}, 2000);
};
return (
<div className="App">
<h1>React UseState: Updating a state object</h1>
{["1", "2"].map(id => {
return !loading[id] ? (
<button key={id} onClick={() => handleOnClick(id)}>
Item {id}
</button>
) : (
"Loading..."
);
})}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
答案 0 :(得分:4)
状态更新在React中不是同步的,这是在基于先前状态更新状态时的常见问题。我认为您需要进行以下更改:
const handleOnClick = id => {
setLoading(prev => ({ ...prev, [id]: true }));
setTimeout(() => {
// simulate the case for when error is returned after an api call.
setLoading(prev => ({ ...prev, [id]: false }));
}, 2000);
};
我已经更改了setLoading
行,以在更新中使用以前的状态。
您可以在此处了解更多信息:
https://reactjs.org/docs/hooks-reference.html#functional-updates
答案 1 :(得分:0)