local storage – Issue with react context. Context lost on page refresh

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.

Product of the Month September 2016

Source link

Leave a Comment

Your email address will not be published. Required fields are marked *