-2

I am creating a user session asking the server through an api if the session already exists and if it exists change the state to the session to true but I get this error "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. "

const [session, setSession] = useState();
    Axios.defaults.withCredentials = true;

    useEffect(() => {
        Axios.get('http://localhost:3001/admin/api/session').then((res) => {
            if (res.data.login === true){
                setSession(true);
            }
        })
    }, []);

    if(session){
        return <Route {...restoDePropiedades}>{children}</Route>
    }else{
        return <Redirect to="/admin-login"/>
    }
Steve Holgado
  • 11,508
  • 3
  • 24
  • 32
Brayan
  • 3
  • 1
  • Does this answer your question? [Can't perform a React state update on an unmounted component](https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component) – Ryan Schaefer Aug 11 '21 at 16:57

2 Answers2

0

The problem is that your component has unmounted before the async Axios request completes. Therefore, it's trying to call setSession after the component has unmounted.

You can use a ref to store the mounted state of the component and use it in an if condition when the Axios request completes:

const unmounted = useRef(false);

useEffect(() => {
  Axios.get('http://localhost:3001/admin/api/session').then((res) => {
    // Check if component has unmounted before trying to update state
    if (!unmounted.current) {
      if (res.data.login === true) {
        setSession(true);
      }
    }
  })
}, []);

useEffect(() => {
  // This function will run when the component unmounts
  return () => {
    unmounted.current = true;
  }
}, []);
Steve Holgado
  • 11,508
  • 3
  • 24
  • 32
  • this will just introduce a race condition between the API response and React rendering the component for the first time as `session` is initially `undefined`, and React will always win in this case – andy mccullough Aug 11 '21 at 17:09
  • I used your answer but inside the useEffect for some reason it takes the value of unmounted as true and does not do the if condition – Brayan Aug 11 '21 at 17:57
  • And if I remove the exclamation mark, I get the same error in the browser console – Brayan Aug 11 '21 at 17:58
0

You could follow the approach that each component that makes an async request should handle at least the most common states, e.g. loading and error, so you could introduce a loading state at the very least, especially if you need to check the session against the API before doing anything

e.g.

const [session, setSession] = useState();
const [loading, setLoading] = useState(true)

useEffect(() => {
   Axios.get('http://localhost:3001/admin/api/session').then((res) => {
      if (res.data.login === true){
         setSession(true);
      }
   })
   .finally(() => setLoading(false))
}, []);

if (loading) return <Loading />

if(session){
    return <Route {...restoDePropiedades}>{children}</Route>
}else{
    return <Redirect to="/admin-login"/>
}

or whatever way you need to handle the routes when its loading

andy mccullough
  • 9,070
  • 6
  • 32
  • 55