我之前有這個錯誤
警告:無法對未安裝的組件執行 React 狀態更新。這是一個空操作,但它表明您的應用程式中存在記憶體泄漏。要解決此問題,請在 useEffect 清理函式中取消所有訂閱和異步任務。
這是我useEffect從firestore檢索資料的地方,它確實消除了錯誤:
useEffect(async () => {
let isMounted = true;
const querySnapshot = await getDocs(collection(db, "product"));
const arr = [];
querySnapshot.forEach((doc) => {
arr.push({
...doc.data(),
id: doc.id,
});
if (isMounted) setProduct(arr);
});
return () => {
isMounted = false;
};
}, []);
沒關系還是這useEffect會在未來引起任何問題?我安裝對了嗎?
uj5u.com熱心網友回復:
查看您當前的代碼,您useEffect使用一個async使用await. 因為您使用的是async函式,所以您回傳的取消訂閱函式useEffect被包裝在 aPromise中,而不是原始回呼本身。這意味著useEffect永遠不會及時看到回傳值是一個回呼函式,以便它有用。
解決這個問題的方法是確保傳入的函式useEffect不是async。
useEffect(() => {
let isMounted = true;
const doFetch = async () => {
const querySnapshot = await getDocs(collection(db, "product"));
const arr = [];
querySnapshot.forEach((doc) => {
arr.push({
...doc.data(),
id: doc.id,
});
if (isMounted) setProduct(arr);
});
};
doFetch() // start the async work
.catch((err) => {
if (!isMounted) return; // unmounted, ignore.
// TODO: Handle errors in your component
console.error("failed to fetch data", err);
});
return () => {
isMounted = false;
};
}, []);
有些useAsyncEffect實作允許您跳過當前使用的樣板setState()。useEffect()我已在此處和此處的類似答案中詳細說明了這些內容。
uj5u.com熱心網友回復:
這看起來不錯。但最好將獲取邏輯提取到一個單獨的函式中,而不是將整個邏輯放在useEffect. 如果請求在掛載時失敗,重試等功能的邏輯很容易重用。
我會做這樣的事情......
- 注意:我洗掉了
isMounted作為安裝組件時運行的效果。 - 將函式包裝在 useEffect 內的異步函式(命名或匿名)中并立即運行它。
// Re-usable logic for stuff like reload/retry
const fetchProduct = async () => {
const querySnapshot = await getDocs(collection(db, "product"));
const arr = [];
querySnapshot.forEach((doc) => {
arr.push({
...doc.data(),
id: doc.id,
});
});
setProduct(arr); // Moved this out of the loop to be run once.
}
useEffect(async () => {
(async () => {
await fetchProduct();
// await other async operations here.
})(); // This immediately runs the func async.
}, []);
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/427826.html
標籤:javascript 反应 火力基地 谷歌云火库
上一篇:如何將我的元素定位為粘性(當我滾動通過它們時留在螢屏上)
下一篇:上傳后在div中顯示img
