So I am getting this 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.
in Products (created by Context.Consumer)*
Well, it's occurring in the Products Component When I Reroute to Product Edit component! Products component is used to list all products and product edit is used to edit product details and both these components are connected to the same context API using useContext. My Context API provider looks like this
*import React, { useState , createContext , useEffect} from 'react';
import firebase from "../firebase";
export const ProdContext = createContext();
const ProdContextProvider = props => {
const [products , setproducts]= useState([])
const [loading , setloading] = useState(true)
const [subcribe , setsubcribe] = useState(false)
const unsub =()=>{
setsubcribe(false);
console.log("unsubcribe--"+subcribe)
}
const sub =()=>{
setsubcribe(true);
console.log("subcribe--"+subcribe)
}
useEffect(() => {
let mounted = true;
setloading(true)
async function fetchData() {
setloading(true);
await firebase.firestore()
.collection("products")
.onSnapshot((snapshot)=>{
const data = snapshot.docs.map((doc)=>(
{
id : doc.id,
...doc.data()
}
))
console.log("b4 if--"+subcribe)
if(subcribe){
console.log("in if--"+subcribe)
setproducts(data)
setloading(false)
}
})
}
fetchData();
return () => mounted = false;
}, [subcribe])
console.log("after getting bottom"+subcribe)
return (
<ProdContext.Provider value={{subcribe:subcribe,prodloading:loading, products: products, loading:loading , sub:sub , unsub:unsub}}>
{props.children}
</ProdContext.Provider>
);
}
export default ProdContextProvider;*
And my products Component looks like this:
export default function Products(props){
const {products , loading ,sub , unsub,subcribe}= useContext(ProdContext)
const [selectid, setselectid] = useState("")
const [ShowLoading, setShowLoading] = useState(true);
const [showAlert2, setShowAlert2] = useState(false);
const [redirect , setredirect] = useState(false)
const [value, setValue] = useState(null);
const [inputValue, setInputValue] = useState('');
useEffect(() => {
sub();
console.log("product mound--"+subcribe)
}, [])
useEffect(() => {
return () => {
console.log("product unsub--"+subcribe)
unsub();
console.log("product unmound--"+subcribe)
};
}, []);
if (redirect) {
return <Redirect push to={{
pathname: `/products/${selectid}`,
}} />;
}
return ( .........)}
Product Edit Component:
const Productedit = (props) => {
const {products,loading , subcribe} = useContext(ProdContext);
const { sub,unsub } = useContext(ProdContext);
const [formData, setformData] = useState({});
const {category} = useContext(CatContext)
const [showLoading, setShowLoading] = useState(false);
const [mainurl, setmainurl] = useState(null);
const [imggal, setimggal] = useState([]);
const [situation , setsituation] = useState("")
const [redirect , setredirect] = useState(false)
const [showAlert, setShowAlert] = useState(false);
const [msg, setmsg] = useState(true);
useEffect(() => {
sub();
console.log("productedit mound--"+subcribe)
return () => unsub();
}, [])
...........
Well I think the issue is that products component is still subscribed to getproduct provider even when it is unmounted but I cant get to solve the issue anyone can help
The issue is not related to Firestore rather this seems to be a common issue with react.
We just no need to update the state in the callback if the component is not mounted already.
It's better to check before updating the state by adding an if block in the async function
if(mounted) {// Code inside the async tasks}
Please refer here [1] for additional information about this warning.
[1] https://www.debuggr.io/react-update-unmounted-component/#state-updates
(This should have been a comment as I don't have enough reputation hence posting as an answer)
Hope I understood the question right and the suggestion helps!