I am trying to use useEffect hook of react to render a component(SideNavbar) but the component(SideNavbar) is not changing until i reload the page manually.
The system works when i reload the page but how can i do it without having to manualy reload the page.
I need to remove a Sidenavbar when user is not logged in and display the navbar when user is logged in.
How to make the component rerender as soon as the user has succesfully logged in?
Also How to hide the component (SideNavbar) as soon as the user logs Out.
import Navbar from "./Components/Navbar";
import React, { useEffect, useState } from "react";
import { Route,Routes } from "react-router";
import Home from "./Routes/Home";
import Contact from "./Routes/Contact";
import Enroll from "./Routes/Enroll";
import Login from "./Routes/Login";
import SideNavbar from "./Components/InnerComponents/SideNavbar";
import Profile from './Routes/Admin/Profile';
import Notice from './Routes/Admin/Notice';
import Result from './Routes/Admin/Result';
import StudentList from "./Routes/Admin/StudentList";
import TeacherList from "./Routes/Admin/TeacherList";
import Classroom from "./Routes/Admin/Classroom";
import NoticeState from "./context/notices/NoticeState";
import NewAccount from "./Routes/Admin/NewAccount.js"
import UserState from "./context/user/UserState";
function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(()=>{
if(localStorage.getItem('token')){
setIsLoggedIn(true);
}
},[localStorage.getItem('token')])
return (
<div className="App">
<UserState>
<NoticeState>
<Navbar/>
{isLoggedIn && <SideNavbar/>}
<div className="containerApp">
<Routes>
<Route element={<NewAccount/>} exact path='/newaccount' />
<Route element={<Profile/>} exact path='/profile' />
<Route element={<Notice/>} exact path="/notice"/>
<Route element={<Result/>} exact path="/result"/>
<Route element={<TeacherList/>} exact path="/teacherList" />
<Route element={<Classroom/>} exact path="/classroom" />
<Route element={<StudentList/>} path="/classroom/:classID"/>
<Route element={<Home/>} exact path='/' />
<Route element={<Contact/>} exact path='/contact' />
<Route element={<Enroll/>} exact path='/enroll' />
<Route element={<Login/>} exact path='/login' />
</Routes>
</div>
</NoticeState>
</UserState>
</div>
);
}
export default App;
2
Answers
The problem is in this
useEffect
Because in deps array, there is
localStorage.getItem('token')
, which is called once, the<App/>
has no reason to rerender (which is caused bysetState
).The quickest solution is to create a periodical check if there is a token in the
localStorage
.It will work, but it’s not an ideal solution. Here are some reasons why:
localStorage
is convenient, but comes with many, many drawbacks. It can leak easily, so it’s not a recommended way. You can read more in this SO post.React
reactivity system and automatic updates on e.g.setState
orReact.Context
value changes, we should rather look for a solution, that after logging in and obtaining the token will cause automatic rerender of the<App/>
e.g. by updatingReact.Context
value, setting the state. The clue is, that you should trigger this rerender on successful login by setting up a value that will update<App/>
component.React
will take care of rest related to rerendering and showingSidebar
.You need to re-render the component as user successfully logs in / logs out.
Use useEffect dependancy stated as in below code.
Check this updated code.