首页 > 解决方案 > 反应上下文的问题。页面刷新时上下文丢失

问题描述

我对上下文有点困惑,而且我是 ReactJS 的新手。我尝试实现登录机制并拥有一些受保护的路由,但是当我刷新页面时,上下文丢失了,尽管我将所需的一切都保存在本地存储中。这是我所做的。

语境:

import {createContext} from 'react'

export const AuthContext = createContext({
    isLoggedIn: false,
    userId:null,
    role:null,
    username:null,
    token: null,
    login: () => {},
    logout: () => {}
})

授权钩子:

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 };


}

应用程序.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;

保护路线:

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

当我登录时,一切都按预期工作,直到我刷新我所在的页面。然后,我总是被重定向到 LoginPage。

我什至尝试在 AuthHook 中使用 Effect 从 localStorage 重新加载所有内容。

我在这里缺少什么?提前致谢。

标签: local-storagereact-context

解决方案


推荐阅读