reactjs 在完全刷新之前,我的身份验证上下文提供程序状态变量不会更新

von4xj4u  于 2023-02-22  发布在  React
关注(0)|答案(1)|浏览(103)

我有一个身份验证上下文提供程序,其中包含令牌和角色的状态变量以及登录和注销函数。我无法让注销函数工作。在我单击调用注销函数的链接后,我仍然可以导航到受保护的页面。我控制退出角色和令牌,它仍然显示它们已填充。在我执行刷新后,它会清除它们并强制我登录。
下面是我的useAuth.js:

import { createContext, useContext, useMemo } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useSessionStorage } from './useSessionStorage';
import { authenticateUser } from '../utils/APIFunctions';

const AuthContext = createContext(undefined);

export const AuthProvider = ({ children }) => {
    const [token, setToken] = useSessionStorage('token', null);
    const [role, setRole] = useSessionStorage('userRole', null);
    const navigate = useNavigate();

    const login = async (data) => {
        const password = data.password;
        const navigateTo = data.navigateTo;
        const roles = data.roles;
        // check this password in the DB
        let error = '';
        const result = await authenticateUser(password);

        const authLevel = result?.data[0]?.auth_level;
        let theRole;
        switch (authLevel) {
            case 99:
                theRole = 'SuperAdmin';
                break;
            case 1:
                theRole = 'User';
                break;
            case 2:
                theRole = 'Admin';
                break;
            case 3:
                theRole = 'Regulator';
                break;
            case 4:
                theRole = 'QC';
                break;
            default:
                theRole = 'none';
        }
        setRole(theRole);
        if (result?.status === 200 && authLevel > 0) {
            // this is a valid password
            if (roles.includes(theRole)) {
                // they are allowed to access the page they are attempting to access
                const time = Date.now();
                setToken({ token: password + '-' + time });
                navigate(navigateTo);
            } else {
                // show unauthorized message/page
                error = 'You do not have access to this page.';
            }
        } else {
            if (result.data.name === 'ConnectionError') {
                error = 'Unable to connect to database.';
            } else if (result?.data?.ReturnValue === 0) {
            } else {
                error = 'Error logging into Scheduler.';
            }
        }
        return error;
    };

    const logout = (redirect = true) => {
        sessionStorage.clear();
        setToken(null);
        setRole(null);
        if (redirect) {
            navigate('/', { replace: true });
        }
        location.reload();  // i would like to remove this, the hard refresh causes a white page until the app reloads
    };

    const value = useMemo(
        () => ({
            token,
            role,
            login,
            logout,
        }),
        [token, role]
    );

    return (
        <AuthContext.Provider value={value}>
            {children}
        </AuthContext.Provider>
    );
};

export const useAuth = () => {
  return useContext(AuthContext);
};

然后是我的ProtectedRoute.js,它检查并验证令牌和角色:

import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../hooks/useAuth';
import { Roles } from './Roles';

export const ProtectedRoute = ({ children, roles }) => {
    const { token, role } = useAuth();
    console.log({ token, role });
    const location = useLocation();

    if (
        !token ||
        (!roles.includes(Roles.Everyone) && !roles.includes(role))
    ) {
        // user is not authenticated
        return (
            <Navigate
                to={'/login'}
                state={{ from: location, roles }} // <-- pass in route state
                replace
            />
        );
    }
    return children;
};

下面是useSessionStorage.js:

import { useState } from 'react';

export const useSessionStorage = (keyName, defaultValue) => {
    const [storedValue, setStoredValue] = useState(() => {
        try {
            const value = window.sessionStorage.getItem(keyName);

            if (value) {
                return JSON.parse(value);
            } else {
                if (defaultValue) {
                    window.sessionStorage.setItem(
                        keyName,
                        JSON.stringify(defaultValue)
                    );
                }
                return defaultValue;
            }
        } catch (err) {
            return defaultValue;
        }
    });

    const setValue = (newValue) => {
        if (newValue) {
            try {
                window.sessionStorage.setItem(
                    keyName,
                    JSON.stringify(newValue)
                );
            } catch (err) {}
            setStoredValue(newValue);
        }
    };

    return [storedValue, setValue];
};
wswtfjt7

wswtfjt71#

更新useSessionStorage()setValue的代码,以便正确处理错误值。
可能取决于您的特定使用情形,但类似于:

const setValue = (newValue) => {
        if (newValue) {
            try {
                window.sessionStorage.setItem(
                    keyName,
                    JSON.stringify(newValue)
                );
            } catch (err) {}
        }
        else {
            window.sessionStorage.removeItem(keyName);
        }

        setStoredValue(newValue);
    };

相关问题