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

React私有路由刷新跳转登录页,加载逻辑失效问题求助

问题

在React应用中使用Redux + RTK Query实现私有路由时,刷新私有页面会直接跳转到登录页,无法进入isLoading分支显示加载状态。虽然刷新后Redux Store的用户信息最终会更新,但导航跳转已经提前触发。


相关代码

RequireAuth组件代码

import { ReactNode } from "react";
import { useAppSelector } from "../../redux/hooks";
import { Navigate, useLocation } from "react-router-dom";

const RequireAuth = ({ children }: { children: ReactNode }) => {
  const location = useLocation();
  const { user, isLoading } = useAppSelector((state) => state?.auth);

  if (isLoading) {
    return <p>Loading.............</p>;
  }
  if (!user?.email && !isLoading) {
    return <Navigate to="/login" state={{ from: location }}></Navigate>;
  }
  return children;
};

export default RequireAuth;

Auth Slice初始状态与代码

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  user: {
    email: "",
    accountStatus: "",
    role: "",
    id: "",
  },
  isLoading: false,
};

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    userLoggedIn: (state, action) => {
      const { accessToken, ...userInfo } = action.payload;
      state.user = userInfo;
    },
    userLoggedOut: (state) => {
      state.user = {
        email: "",
        accountStatus: "",
        role: "",
        id: "",
      };
    },
    toggleLoading: (state) => {
      state.isLoading = !state.isLoading;
    },
  },
});

export const { userLoggedIn, userLoggedOut, toggleLoading } = authSlice.actions;

export default authSlice.reducer;

RTK Query persistLogin端点代码

const authApi = api.injectEndpoints({
  endpoints: (builder) => ({
    persistLogin: builder.query({
      query: (payload) => ({
        url: "/auth/persist-login",
        method: "GET",
        body: payload,
      }),
      async onQueryStarted(_data, { dispatch, queryFulfilled }) {
        try {
          dispatch(toggleLoading());
          const result = await queryFulfilled;
          dispatch(userLoggedIn(result.data.data));
          dispatch(toggleLoading());
        } catch (error) {
          // nothing to do here
        }
      },
    }),
  }),
});

注:在App.tsx中调用usePersistLoginQuery钩子,用于页面刷新时持久化用户信息。


修复方案

1. 修正初始加载状态的默认值

页面刷新后Redux Store重置为初始状态,此时user.email为空,且初始isLoading为false,导致RequireAuth直接触发跳转。将初始isLoading设为true,确保身份验证请求完成前先显示加载状态:

// authSlice.js
const initialState = {
  user: {
    email: "",
    accountStatus: "",
    role: "",
    id: "",
  },
  isLoading: true, // 改为true
};

2. 改用RTK Query内置的加载状态(更可靠)

手动维护toggleLoading容易出现时机偏差,直接使用RTK Query钩子返回的isLoading状态,能精准对应请求的生命周期:

  • 修改RequireAuth组件:
import { ReactNode } from "react";
import { useAppSelector } from "../../redux/hooks";
import { Navigate, useLocation } from "react-router-dom";
import { usePersistLoginQuery } from "../../redux/services/authApi";

const RequireAuth = ({ children }: { children: ReactNode }) => {
  const location = useLocation();
  const { user } = useAppSelector((state) => state?.auth);
  // 直接获取RTK Query的请求加载状态
  const { isLoading } = usePersistLoginQuery(/* 传入persistLogin所需的payload,如localStorage中的token */);

  if (isLoading) {
    return <p>Loading.............</p>;
  }
  if (!user?.email) {
    return <Navigate to="/login" state={{ from: location }}></Navigate>;
  }
  return children;
};

export default RequireAuth;
  • 移除手动加载状态相关代码:
    • 删除authSlice中的toggleLoading reducer及导出
    • 删除persistLogin端点中的dispatch(toggleLoading())调用

3. 确保persistLogin请求的执行时机

在App.tsx中调用usePersistLoginQuery时,不要设置skip参数,确保应用初始化时立即触发身份验证请求:

// App.tsx
import { usePersistLoginQuery } from "./redux/services/authApi";

function App() {
  // 直接调用钩子,页面加载时自动触发请求
  usePersistLoginQuery(/* 传入必要的验证参数 */);

  return (
    <Router>
      {/* 路由配置 */}
    </Router>
  );
}

核心原因

页面刷新后Redux Store重置,初始状态下user.email为空且isLoading为false,RequireAuth会立即执行跳转逻辑;而persistLogin是异步请求,完成后更新用户信息时,跳转已经完成。通过调整初始加载状态或依赖RTK Query的内置状态,可确保身份验证过程中先显示加载,再判断是否跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:37:46