You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Context刷新/页面切换后重置为默认值问题求助

解决React Context授权状态刷新/页面切换后重置的问题

问题根源

React组件的状态(包括Context维护的state)仅存储在内存中,页面刷新或重新加载时,所有组件会重新初始化,state会回归默认值。要解决这个问题,必须将认证状态持久化到本地存储(localStorage/sessionStorage),在应用启动时重新读取并恢复状态。

具体解决方案

1. 修改AuthProvider,添加状态持久化逻辑

更新AuthProvider组件,初始化时从本地存储读取认证信息,状态变化时同步更新本地存储:

// AuthContext.tsx
import { createContext, useState, useEffect, useContext, ReactNode } from 'react';

interface AuthData {
  user: string;
  pwd: string;
  roles: string;
  accessToken: string;
}

interface AuthContextValue {
  auth: AuthData | null;
  setAuth: React.Dispatch<React.SetStateAction<AuthData | null>>;
}

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

interface AuthProviderProps {
  children: ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  // 初始化时从localStorage读取已保存的认证信息
  const [auth, setAuth] = useState<AuthData | null>(() => {
    const savedAuth = localStorage.getItem('auth');
    return savedAuth ? JSON.parse(savedAuth) : null;
  });

  // 当auth状态变更时,同步到localStorage
  useEffect(() => {
    if (auth) {
      localStorage.setItem('auth', JSON.stringify(auth));
    } else {
      localStorage.removeItem('auth');
    }
  }, [auth]);

  // 可选:启动时验证token有效性,过期则清除状态
  useEffect(() => {
    if (auth?.accessToken) {
      const validateToken = async () => {
        try {
          await axios.get('/api/validate-token', {
            headers: { Authorization: `Bearer ${auth.accessToken}` }
          });
        } catch (err) {
          // token无效,清除认证状态
          setAuth(null);
        }
      };
      validateToken();
    }
  }, [auth]);

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

// 自定义hook,避免重复编写useContext逻辑
export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth必须在AuthProvider内部使用');
  }
  return context;
};

export default AuthContext;

2. 优化登录逻辑(安全建议)

登录成功后无需保存密码到Context和本地存储,密码仅用于登录请求,后续依赖token完成授权,降低敏感信息泄露风险:

// Login.tsx
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
      }
    );
    const accessToken = response?.data?.accessToken;
    const roles = 'to implement'; // 替换为后端返回的角色数据
    // 仅保存必要认证信息,移除密码字段
    setAuth?.setAuth({ user, roles, accessToken, pwd: '' });
    setUser('');
    setPwd('');
    navigate(from, { replace: true });
  } catch (err) {
    setErrMsg('Login Failed');
  }
};

关键注意事项

  • 存储选择:localStorage会持久保存至手动清除,sessionStorage在浏览器关闭后自动清除,可根据业务需求选择。
  • 安全防护:禁止在本地存储中保存敏感信息(如明文密码),确保接口请求使用HTTPS传输,防止token被窃取。
  • 状态同步:所有修改auth状态的操作(如登录、登出、token刷新)都需触发本地存储的更新,保证状态一致性。

内容的提问来源于stack exchange,提问作者Rasppy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:34:53