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

使用useNavigate切换路由时React Context数据重置问题求助

React-Router-DOM v6 路由跳转后Context数据重置问题排查与解决

1. 修正AuthProvider与BrowserRouter的包裹顺序

你当前用AuthProvider包裹BrowserRouter的写法是错误的,这会导致路由上下文与认证上下文的作用域冲突。正确的顺序应该是让BrowserRouter包裹AuthProvider,确保路由跳转时认证上下文的作用域覆盖所有路由组件:

错误写法:

// App.tsx
<AuthProvider>
  <BrowserRouter>
    <Router />
  </BrowserRouter>
</AuthProvider>

正确写法:

// App.tsx
<BrowserRouter>
  <AuthProvider>
    <Router />
  </AuthProvider>
</BrowserRouter>

2. 缓存AuthContext的value对象

如果AuthProvider每次渲染都生成新的value对象,会触发所有消费上下文的组件强制重渲染,甚至导致状态丢失。用useMemo缓存value:

错误示例:

const AuthProvider = ({ children }) => {
  const [auth, setAuth] = useState({});

  // 每次渲染创建新对象,导致上下文无效更新
  return (
    <AuthContext.Provider value={{ auth, setAuth }}>
      {children}
    </AuthContext.Provider>
  );
};

正确写法:

const AuthProvider = ({ children }) => {
  const [auth, setAuth] = useState({});

  // 仅当auth状态变化时才更新value
  const value = useMemo(() => ({ auth, setAuth }), [auth]);

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

3. 修正Dashboard中状态更新逻辑

确保更新auth上下文时是合并现有状态,而非直接替换为空对象,避免覆盖已有数据:

错误示例:

// Dashboard.tsx
useEffect(() => {
  // 直接替换状态,丢失原有数据
  setAuth({ accessToken: 'xxx' });
}, []);

正确写法:

// Dashboard.tsx
useEffect(() => {
  // 合并现有状态,保留其他字段
  setAuth(prev => ({ ...prev, accessToken: 'xxx' }));
}, []);

4. 检查是否存在多个AuthProvider实例

确保整个应用中只存在一个AuthProvider实例,避免不同路由组件使用独立的上下文实例(比如Router组件内部重复嵌套AuthProvider)。

5. 确认useAuth钩子的正确性

确保useAuth钩子正确消费上下文,避免因上下文未找到导致的异常:

const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth必须在AuthProvider内部使用');
  }
  return context;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:43:19