'Best practices for async await when retrieving data from firestore
I had this error before
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
This is my useEffect where I retrieve data from firestore and it does remove the error:
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;
};
}, []);
Is the useEffect alright or will this cause any problems in the future? And am I mounting this right?
Solution 1:[1]
Ths look okay. But it's best to extract the fetching logic into a separate function instead of having the entire logic in the body of the useEffect. It gets easy to re-use the logic for functionality like retrying if the request failed on mount.
I would do something like this...
- Note: I removed the
isMountedas the effect with be run when the component is mounted. - Wrap the function in an async function(named or anonymous) inside the useEffect and run it immediately.
// 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.
}, []);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | iamcastelli |
