React Context 重置为默认值

问题描述 投票:0回答:1

我尝试过使用 React Context 在网站上进行授权。我似乎每当刷新页面或更改页面时,上下文都会重置为默认值。我对 React 和 Web 开发还很陌生,我一直在关注这个教程。 我在我的项目中使用 Typescrypt(而不是像教程中那样的 js)、React、axios 和 jwt。

我的后端运行良好,我可以注册和验证用户。

这是我使用的上下文:

//The value of the context (State and setState)
interface AuthContextValue{
    auth : {user: string ,pwd:string,roles:string,accessToken:string} | null;
    setAuth : React.Dispatch<React.SetStateAction<{user:string,pwd:string,roles:string,accessToken:string} | null>>;
}


const AuthContext = createContext<AuthContextValue| undefined>(undefined);

interface AuthProviderProps {
    children : React.ReactNode;
}

//Provider to wrap around the parent components which children/distant children might need the user logged
export const AuthProvider: React.FC<AuthProviderProps> = ({children}) => {
    const [auth, setAuth] = useState<{user:string,pwd:string,roles:string,accessToken:string} | null>(null);

    return (
        <AuthContext.Provider value={{ auth, setAuth }}>
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContext;

这是我将上下文提供程序包装在我的应用程序中的索引

const container = document.getElementById('root');
if (container) {
    const root = createRoot(container);
    root.render(
    <AuthProvider>
        <App/>
    </AuthProvider>
    
    );
} else {
    console.error('Failed to find the root element');
}

在我的应用程序中,我声明了我的路线,其中一条是私有的:

                <Route element={<RequireAuth />}>
                <Route path="/private" element = {<PrivateTestPage/>}/>
                </Route>

这是 RequireAuth :

function RequireAuth() {
    const auth = useAuth()?.auth;
    const location = useLocation();

    return (
        auth?.user
            ? <Outlet/>
            : <Navigate to="/login" state = {{from : location}} replace/>
 
    );
}

export default RequireAuth

最后是我的登录页面:

const Login = (props:any) => {
    const setAuth = useAuth();

    const navigate = useNavigate();
    const location = useLocation();
    const from = location.state?.from?.pathname || "/";

    const userRef = useRef(null);
    const errRef = useRef(null);

    const [user, setUser] = useState('');
    const [pwd, setPwd] = useState('');
    const [errMsg, setErrMsg] = useState('');


    useEffect(() => {
        setErrMsg('');
    }, [user, pwd])

    const handleSubmit = async (e: { preventDefault: () => void; }) => {
        e.preventDefault();

        try {
            const response = await axios.post(LOGIN_URL,
                JSON.stringify({ loginId:user, password:pwd }),
                {
                    headers: { 'Content-Type': 'application/json' },
                    withCredentials: true
                }
            );
            console.log(JSON.stringify(response?.data));
            console.log(JSON.stringify(response));
            const accessToken = response?.data?.accessToken;
            const roles = 'to implement' //response?.data?.roles;
            setAuth?.setAuth({ user, pwd, roles, accessToken });
            setUser('');
            setPwd('');
            navigate(from, {replace:true})
        } catch (err) {
            setErrMsg('Login Failed');
        }
    }

    return (
        <>
                <section>
                    <p ref={errRef} className={errMsg ? "errmsg" : "offscreen"} aria-live="assertive">{errMsg}</p>
                    <h1>Sign In</h1>
                    <form onSubmit={handleSubmit}>
                        <label htmlFor="username">Username:</label>
                        <input
                            type="text"
                            id="username"
                            ref={userRef}
                            autoComplete="off"
                            onChange={(e) => setUser(e.target.value)}
                            value={user}
                            required
                        />

                        <label htmlFor="password">Password:</label>
                        <input
                            type="password"
                            id="password"
                            onChange={(e) => setPwd(e.target.value)}
                            value={pwd}
                            required
                        />
                        <button>Sign In</button>
                    </form>
                    <p>
                        Need an Account?<br />
                        <span className="line">
                            <a href={REGISTERPAGE_URL}>Sign Up</a>
                        </span>
                    </p>
                </section>
        </>
    )
}

export default Login

在显示所有页面的主页中,我添加了一个段落,让我看看上下文中是否有内容

<p>{setAuth?.auth?.user}</p>
。当用户在登录页面进行身份验证时,它会返回到之前浏览的页面。

当我浏览主页后登录时,我可以看到上下文检索了用户,但是一旦刷新页面,或更改页面并返回主页,上下文就会重置。

reactjs authorization react-context
1个回答
0
投票

看来上下文值应该在刷新后重置。数据只是在会话之间不保存。

在这种情况下,最好使用 Redux 并将数据存储在本地实例或 cookie 中。它与该项目相得益彰。

再次强调,我不是专业人士,但如果您遇到类似问题,请查看 Redux 教程。

© www.soinside.com 2019 - 2024. All rights reserved.