Getting the following error on all child components.
react-dom.development.js:86 Warning: Cannot update a component (
PrivateRoute
) while rendering a different component (Example
). To locate the bad setState() call insideExamples
,
I've found lots of examples of the same error but thus far no solutions React Route Warning: Cannot update a component (`App`) while rendering a different component (`Context.Consumer`) Can Redux cause the React warning "Cannot update a component while rendering a different component"
The PrivateRoute wraps the component to redirect if not logged in.
export default function PrivateRoute() {
const session: ISessionReducer = useSelector((state: RootState) => state.core.session);
useEffect(() => {
if (!session.jwt) <Navigate to="/login" />;
}, [session]);
return <Outlet />;
};
CodePudding user response:
It is happening because useEffect
runs after the component is rendered. So what's happening in this case is that your Outlet
component is getting rendered first before your code in useEffect
runs. So if the jwt token
doesn't exist then it will try to redirect but it won't be able to because your Outlet
will already be rendered by then.
So I can give you the solution of what I use to check if the jwt token
exist.
1.) I create a custom hook for checking if the token
exists.
2.) And then I use that custom hook in my privateRoute
component to check if the user is loggedIn.
useAuthStatus.js
import { useState, useEffect } from 'react'
import { useSelector } from 'react-redux'
export const useAuthStatus = () => {
const [loggedIn, setLoggedIn] = useState(false)
const [checkingStatus, setCheckingStatus] = useState(true)
const { user } = useSelector((state) => state.auth)
useEffect(() => {
if (user?.token) {
setLoggedIn(true)
} else {
setLoggedIn(false)
}
setCheckingStatus(false)
}, [user?.token])
return { loggedIn, checkingStatus }
}
PrivateRoute component
import { Navigate, Outlet } from 'react-router-dom'
import { useAuthStatus } from '../../hooks/useAuthStatus'
import CircularProgress from '@mui/material/CircularProgress'
const PrivateRoute = () => {
const { loggedIn, checkingStatus } = useAuthStatus()
if (checkingStatus) {
return <CircularProgress className='app__modal-loader' />
}
return loggedIn ? <Outlet /> : <Navigate to='/login' />
}
export default PrivateRoute