我有一個功能組件,我正在為這樣的復雜物件宣告一個 useState:
const [order, setOrder] = useState<IMasterState>({
DataInterface: null,
ErrorMsg: "",
IsRetrieving: true,
RetrievingMsg: "Fetching your order status..."
});
我現在嘗試order通過呼叫setOrder像這樣的 useEffect來設定狀態:
useEffect(() => {
(async function() {
let dh = new DataInterface("some string");
let errMsg = "";
// Get the sales order.
try
{
await dh.FetchOrder();
}
catch(error: any)
{
errMsg = error;
};
setOrder(salesOrder => ({...salesOrder, IsRetrieving: false, ErrorMsg: errMsg, DataInterface: dh}));
})();
}, []);
按原樣,這似乎作業正常。但是,我有一個 setInterval 物件,它可以在order.IsRetrievingis 時更改螢屏訊息true:
const [fetchCheckerCounter, setFetchCheckerCount] = useState<number>(0);
const statusFetcherWatcher = setInterval(() => {
if (order.IsRetrieving)
{
if (fetchCheckerCounter === 1)
{
setOrder(salesOrder => ({...salesOrder, RetrievingMsg: "This can take a few seconds..."}));
}
else if (fetchCheckerCounter === 2)
{
setOrder(salesOrder => ({...salesOrder, RetrievingMsg: "Almost there!.."}));
}
setFetchCheckerCount(fetchCheckerCounter 1);
}
else
{
// Remove timer.
clearInterval(statusFetcherWatcher);
}
}, 7000);
問題是order.IsRetrieving始終true針對該代碼塊,即使它確實更改為false,并且我的網站更改以反映這一點,甚至顯示來自dh.FetchOrder(). 這意味著我的計時器在后臺無限回圈。
那么我order是否正確設定了狀態?在網上找到一個明確的答案是非常困難的,因為所有的答案都是關于向陣列添加一個新專案。
uj5u.com熱心網友回復:
問題
- 您將間隔設定為函式體中的無意副作用。
- 您已經關閉了
order.isRetreiving間隔回呼中的初始狀態值。
解決方案
使用掛載useEffect開始間隔,并使用 React ref 在更新時快取狀態值,以便可以在異步回呼中訪問當前值。
const [order, setOrder] = useState<IMasterState>({
DataInterface: null,
ErrorMsg: "",
IsRetrieving: true,
RetrievingMsg: "Fetching your order status..."
});
const orderRef = useRef(order);
useEffect(() => {
orderRef.current = order;
}, [order]);
useEffect(() => {
const statusFetcherWatcher = setInterval(() => {
if (orderRef.current.IsRetrieving) {
if (fetchCheckerCounter === 1) {
setOrder(salesOrder => ({
...salesOrder,
RetrievingMsg: "This can take a few seconds...",
}));
} else if (fetchCheckerCounter === 2) {
setOrder(salesOrder => ({
...salesOrder,
RetrievingMsg: "Almost there!..",
}));
}
setFetchCheckerCount(counter => counter 1);
} else {
// Remove timer.
clearInterval(statusFetcherWatcher);
}
}, 7000);
return () => clearInterval(statusFetcherWatcher);
}, []);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/365478.html
