如何使用 useContext 在 Next.js 应用程序中保留用户状态

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

我正在使用 React 和 Next.js 开发一个 Web 应用程序,并且我还有一个作为后端分离的 Node.js API。

我有一个登录表单,我将数据发送到 API 以恢复 JWT,当我这样做时,一切正常,但在将用户重定向到受保护的路由“仪表板”后,或者刷新后,用户上下文会丢失。

这是受保护的路线:

import React, {useContext, useEffect} from 'react'
import { useRouter } from "next/router";
import { Context } from '../../context/context';
export default function DashboardIndexView() {
const router = useRouter();
const {isUserAuthenticated, setUserToken, userToken} = useContext(Context);
useEffect(() => {
    isUserAuthenticated()
    ? router.push("/dashboard")
    : router.push("/authentication/admin");
  }, []);
return (
    <>
    <h1>Dashboard index view</h1>
    </>
)
}

这是上下文文件:

import React, {createContext, useEffect, useState} from 'react'
import { useRouter } from "next/router";
import axios from 'axios'

export const Context = createContext(null)

const devURL = "http://localhost:4444/api/v1/"

export const ContextProvider = ({children}) => {
const router = useRouter()
const [user, setUser] = useState()
const [userToken, setUserToken] = useState()
const [loading, setLoading] = useState(false)
const [successMessage, setSuccessMessage] = useState("")
const [errorMessage, setErrorMessage] = useState("")
const Login = (em,pass) => {
    setLoading(true)
    axios.post(devURL+"authentication/login", {
        email : em,
        password : pass
    })
    .then((res)=>{
        setSuccessMessage(res.data.message)
        setErrorMessage(null)
        setUser(res.data.user)
        setUserToken(res.data.token)
        localStorage.setItem('userToken', res.data.token)
        localStorage.setItem('user', res.data.user)
       
        setLoading(false)
    })
    .catch((err)=>{
        setErrorMessage(err.response.data.message)
        setSuccessMessage(null)
        setLoading(false)
    })
    
}
const Logout = () => {
    
    setUserToken()
    setUser()
    localStorage.setItem('userToken', null)
    localStorage.setItem('user', null)
    router.push('/authentication/admin')
}
const isUserAuthenticated = () => !!userToken

return (
    <Context.Provider value={{
        Login, 
        user, 
        loading,
        userToken,
        setUserToken,
        Logout,
        successMessage,
        setSuccessMessage,
        setErrorMessage,
        isUserAuthenticated,
        errorMessage}}>
        {children}
    </Context.Provider>
)
}

即使发生刷新,如何让用户保持在仪表板页面上?

reactjs next.js jwt server-side-rendering react-context
2个回答
5
投票

useContext()
在页面刷新时丢失其值是正常的。上下文不保存任何数据,它们只是在组件之间共享数据。在 Next.js 中,它可以在页面之间工作,因为 Next.js 处理客户端的导航。但正如您所注意到的,一旦刷新,应用程序就会从头开始安装,这一次上下文永远不会获取 JWT 的值,因为 JWT 从未在应用程序的这个新实例上发送。

从高层次来看,解决方案是将 JWT 存储在某个地方(localStorage 或 cookie)并将值注入到您的

Context.Provider
中。您已经在 localStorage 中设置了值,现在您只需要一个
useEffect
来读取它们并将它们添加到上下文中:

useEffect(() => {
  setUser(localStorage.get('user'));
  setUserToken(localStorage.get('userToken'));
}, []);

但在我看来,真正的解决方案是使用 https://next-auth.js.org/ 代替。它处理安全问题,是 Next.js 的知名库


0
投票

为了避免本地存储未定义值,请使用此值。

 const ISSERVER = typeof window === 'undefined'

    useEffect(() => {
    setUser(!ISSERVER && localStorage.get('user'));
    setUserToken(!ISSERVER && localStorage.get('userToken'));
  }, [])
© www.soinside.com 2019 - 2024. All rights reserved.