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

Zustand更新存储后TanStack Router仍重定向的登录问题求助

解决Zustand + TanStack Router登录时状态更新滞后导致重定向失败的问题

你遇到的核心问题是:第一次点击登录后,Zustand的auth状态更新与路由跳转时机不匹配——路由守卫读取的是Router Context中未更新的旧状态,因此触发重定向回登录页;第二次点击时状态已完成更新,守卫读取到正确状态后正常跳转。

问题根源在于App.tsx中将Zustand的当前state快照传递给了RouterProvider的context,状态更新后Router Context的同步存在滞后,导致导航时守卫无法获取最新状态。


步骤1:传递Zustand Store实例而非状态快照

不要将当前的auth state传给Router Context,而是传递Zustand的store实例,让路由守卫可以随时获取最新状态。

修改store.ts

确保导出Zustand的store实例(或getState方法):

import { create } from 'zustand';

const useGlobalStore = create((set) => ({
  user: null,
  login: async (credentials) => {
    const res = await fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify(credentials),
    });
    const user = await res.json();
    set({ user });
  },
  // 其他auth相关方法
}));

// 导出获取最新状态的方法,用于非组件环境(如路由守卫)
export const getAuthState = useGlobalStore.getState;
export default useGlobalStore;

修改App.tsx

将store的getState方法传入Router Context,而非当前状态:

import { RouterProvider } from '@tanstack/react-router';
import { MantineProvider } from '@mantine/core';
import useGlobalStore, { getAuthState } from './store';
import { router } from './router';
import { workshopWizardTheme, wwVariablesResolver } from './theme';

const App = () => {
  return (
    <MantineProvider theme={workshopWizardTheme} cssVariablesResolver={wwVariablesResolver}>
      <RouterProvider router={router} context={{ getAuthState }} />
    </MantineProvider>
  );
};

export default App;

步骤2:在路由守卫中获取最新状态

修改AppRoute的beforeLoad逻辑,通过传入的getAuthState方法获取实时的auth状态:

// App Route示例
export const Route = createFileRoute('/app')({
  beforeLoad: async ({ context }) => {
    // 获取最新的auth状态
    const authState = context.getAuthState();
    if (!authState.user) {
      return {
        redirect: {
          to: '/auth/login',
        },
      };
    }
  },
  // 其他路由配置
});

步骤3:确保登录完成后再跳转

在AuthPage中,等待登录action执行完成(状态更新后)再执行路由跳转:

import { useRouter } from '@tanstack/react-router';
import useGlobalStore from './store';

const AuthPage = () => {
  const router = useRouter();
  const { login } = useGlobalStore();

  const handleLogin = async (credentials) => {
    // 等待登录状态更新完成
    await login(credentials);
    // 跳转至首页
    router.navigate({ to: '/' });
  };

  return (
    // 登录表单代码
    <button onClick={() => handleLogin({ username, password })}>登录</button>
  );
};

export default AuthPage;

额外说明

  • 避免将可变的状态快照传入Router Context,因为Context的更新依赖组件重渲染,无法保证与状态更新同步。
  • 使用Zustand的getState()方法可以在任何环境(包括路由守卫这种非组件场景)获取最新状态,确保路由判断的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:30:57