This is my primary react file:
// App.tsx
const App: FC = () => {
const isLoggedIn: boolean = localStorage.getItem('logged_user') !== null;
return (
<BrowserRouter>
<Routes>
<Route path="/main" element={isLoggedIn ? <Main/> : <Navigate to='/login'/>}/>
<Route path="/about" element={isLoggedIn ? <About/> : <Navigate to='/login'/>}/>
<Route path="/login" element={<Login/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
After logging in, I store the user in local storage.
I want to achieve the behaviour of redirections to the /login page when the user is not authenticated (when it is not stored in localstorage).
Generally, the above approach works but only sometimes. Sometimes, when I go to '/main', I would get redirected to '/login' even though I was logged in. I assume this is caused by React's nature of re-renders.
How can I approach this?
I'm guessing the redirect to "/login" works the first time, you log in, then try to navigate to "/main" or "/about" and are getting redirected back to "/login" until you do something like a page reload and read any persisted "logged_user" state and then get stuck not being to log out and get redirected back to "/login".
You should store the isLoggedIn
value in local state, initialized from localStorage, and provide a way within the app to toggle the state. Use an useEffect
hook to persist local state changes back to localStorage.
Example:
const App: FC = () => {
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(
() => localStorage.getItem('logged_user') !== null
);
useEffect(() => {
localStorage.setItem('logged_user', JSON.stringify(isLoggedIn));
}, [isLoggedIn]);
const logIn = () => setIsLoggedIn(true);
// pass this callback to components you want to allow logging out
// it will update the local state and then get persisted
const logOut = () => setIsLoggedIn(false);
return (
<BrowserRouter>
<Routes>
<Route path="/main" element={isLoggedIn ? <Main/> : <Navigate to='/login'/>}/>
<Route path="/about" element={isLoggedIn ? <About/> : <Navigate to='/login'/>}/>
<Route path="/login" element={<Login onLogIn={logIn} />}/>
</Routes>
</BrowserRouter>
);
}