I am a bit confused with context and I am new to ReactJS. I try to implement a login mechanism and have some protected routes, but when I refresh the page, context is lost, though I save everything I need at local storage. Here is what I have done.
Context:
import {createContext} from 'react'
export const AuthContext = createContext({
isLoggedIn: false,
userId:null,
role:null,
username:null,
token: null,
login: () => {},
logout: () => {}
})
AuthHook:
import { useState, useCallback, useEffect } from 'react';
import jwt_decode from "jwt-decode";
let logoutTimer
export const useAuth = () => {
const [role, setRole] = useState(null)
const [token, setToken] = useState(null)
const [tokenExpirationDate, setTokenExpirationDate] = useState()
const [username, setUsername] = useState(null)
const [userId, setUserId] = useState(null)
const [isLoggedIn, setIsLoggedIn] = useState(false)
const login = useCallback((user, serverToken) => {
if (localStorage.getItem('user')){
let user = JSON.parse(localStorage.getItem('user'))
let token = user.token
setToken(token)
let decoded = jwt_decode(token)
console.log(decoded)
console.log(decoded.userId)
console.log(decoded.role)
console.log(decoded.username)
setUserId(decoded.userId)
setRole(decoded.role)
setUsername(decoded.username)
setIsLoggedIn(user.isLoggedIn)
}
else {
let expirationDate = new Date(new Date().getTime() + 1000 * 60 * 60)
setTokenExpirationDate(expirationDate)
setToken(serverToken)
setUsername(user.username)
setUserId(user.userId)
setRole(user.role)
setIsLoggedIn(true)
localStorage.setItem('user',
JSON.stringify({
token: serverToken,
isLoggedIn:true,
expiration: expirationDate.toISOString()
}))
}
}, [])
const logout = useCallback(() => {
setToken(null);
setRole(null)
setTokenExpirationDate(null);
localStorage.removeItem('user');
}, [])
useEffect(() => {
if (token && tokenExpirationDate) {
const remainingTime = tokenExpirationDate.getTime() - new Date().getTime();
logoutTimer = setTimeout(logout, remainingTime);
} else {
clearTimeout(logoutTimer);
}
}, [token, logout, tokenExpirationDate]);
useEffect(() => {
const storedData = JSON.parse(localStorage.getItem('user'));
if (
storedData &&
storedData.token &&
new Date(storedData.expiration) > new Date()
) {
//recheck how to implement this
login( storedData.token, username);
}
}, [login]);
useEffect(()=>{
if (localStorage.getItem('user')){
let user = JSON.parse(localStorage.getItem('user'))
let token = user.token
setToken(token)
let decoded = jwt_decode(token)
console.log(decoded)
console.log(decoded.userId)
console.log(decoded.role)
console.log(decoded.username)
setUserId(decoded.userId)
setRole(decoded.role)
setUsername(decoded.username)
setIsLoggedIn(user.isLoggedIn)
}
},[])
return { token, role, login, logout, username, userId, isLoggedIn };
}
App.js
function App() {
const {token, role, login, logout, username, userId, isLoggedIn} = useAuth()
console.log("INSIDE APP")
console.log(token)
console.log(isLoggedIn)
return (
<AuthContext.Provider value={{
isLoggedIn: isLoggedIn,
userId: userId,
role: role,
username:username,
token: token,
login: login,
logout: logout
}}>
<Container style={backgroundStyle}>
<SidebarPage />
<Switch>
<AuthenticatedRoute path="/employeetab" component={EmployeeTab}/>
<AuthenticatedRoute path="/employeeTable" component={EmployeeTable}/>
<AuthenticatedRoute path="/materialsTab" component={Materials}/>
<AuthenticatedRoute path="/worktab" component={WorkTab}/>
<AuthenticatedRoute path="/warehouse" component={InventoryTab}/>
<Route path="/adminPage">
<AdminPage />
</Route>
<AuthenticatedRoute path="/personelTable" component={PersonnelTable}/>
<AuthenticatedRoute path="/sector" component={Sector}/>
<AuthenticatedRoute path="/tools" component={GearTab}/>
<Route path="/not-found">
<NotFound />
</Route>
<AuthenticatedRoute path="/" exact component={Dashboard}/>
<Route path="/login" exact component={LoginComponent}/>
<Redirect to="/not-found" />
</Switch>
</Container>
</AuthContext.Provider>
);
}
export default App;
Protected route:
import React, {useContext} from 'react'
import { Component } from 'react'
import { Route, Redirect } from 'react-router-dom'
import {AuthContext} from "../context/AuthContext";
const AuthenticatedRoute = ({ path, component: Component}) => {
const auth = useContext(AuthContext)
console.log(auth.isLoggedIn)
return (
<Route
path={path}
render={props => {
if (auth.isLoggedIn === false) {
return <Redirect to="/login" />
}
else {
return <Component {...props} />
}
}}
/>
)
}
export default AuthenticatedRoute
When I login everything works as expected until I refresh the page that I am at. Then, I am always redirected to LoginPage.
I have even tried to useEffect at AuthHook to reload everything from localStorage.
What I am missing here? Thanks in advance.