Reputation: 39
I read a lot of similar questions but it seems my questions is a little different.
I am trying to login and I get the following error.
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.
I am attaching the AuthContext.js that handles all the logic hoping you can explain me what is wrong and what knowledge it indicates I need to learn.
import React, { useContext, useState } from 'react'
import {postData} from '../adapters/authAdapter';
const AuthContext = React.createContext();
export function useAuth() {
return useContext(AuthContext);
}
export function AuthProvider({children}) {
const [currentUser,setCurrentUser] = useState(null);
async function login(email,password) {
const adaptedRes = await postData('log-in',{email,password});
if(adaptedRes.err) {
throw new Error(adaptedRes.message)
} else {
return setCurrentUser(adaptedRes.data);
}
}
const value = {
currentUser,
login
};
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
Thank you in advance
Upvotes: 0
Views: 257
Reputation: 4582
The error means that your setCurrentUser()
function is being called, when AuthProvider
is not currently mounted
. That's why, use useRef()
to check if your AuthProvider
is mounted
, and then set state as mentioned in the link:
export function AuthProvider({children}) {
const [currentUser,setCurrentUser] = useState(null);
const isMounted = useRef(false);
useEffect(() => {
// Becomes true on component mount
isMounted.current = true;
// becomes false on unmount
return () => {isMounted.current = false;}
}, [])
async function login(email,password) {
const adaptedRes = await postData('log-in',{email,password});
if(adaptedRes.err) {
throw new Error(adaptedRes.message)
} else {
if(!isMounted.current) {
// Check if component is mounted
console.log('component is not mounted');
return;
}
return setCurrentUser(adaptedRes.data);
}
}
const value = {
currentUser,
login
};
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
Update As Drew Pointed out:
Issue is as others say, the AuthProvider component is being unmounted before setCurrentUser is called. Instead of putting a band-aid fix in to keep the state update from occurring you should figure out why your auth provider isn't mounted. This is one of those provider components you typically want wrapping your entire app and mounted at all times. My guess is you've narrowed the scope of this auth provider too much to just around your auth component UI and then you navigate elsewhere and the provider is no longer available.
So, you should also check this, as if you are getting this error, then there is implementation problem somewhere.
Upvotes: 1