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

React路由保护问题:useSelector初始返回null导致误跳转至登录页

路由保护问题解决方案

问题核心:Redux初始状态中userData.user为null,useSelector会立即返回该值,导致AuthProvider直接跳转到登录页,无法等待用户登录状态初始化完成。

解决步骤

1. 在Redux状态中添加加载状态

修改用户状态的初始值,增加isLoading字段标识用户信息是否正在初始化:

// userSlice.js
const initialState = {
  user: null,
  isLoading: true, // 初始为true,等待登录状态校验
};

2. 添加初始化用户状态的异步逻辑

创建异步Thunk,在应用启动时从本地存储(如localStorage)校验登录状态并更新Redux:

// userSlice.js
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const initializeUser = createAsyncThunk(
  'user/initialize',
  async () => {
    const token = localStorage.getItem('authToken');
    if (token) {
      // 调用后端接口获取用户信息
      const res = await fetch('/api/auth/user', {
        headers: { Authorization: `Bearer ${token}` }
      });
      return res.ok ? await res.json() : null;
    }
    return null;
  }
);

const userSlice = createSlice({
  name: 'userData',
  initialState,
  reducers: {
    // 其他用户操作reducer
  },
  extraReducers: (builder) => {
    builder
      .addCase(initializeUser.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(initializeUser.fulfilled, (state, action) => {
        state.user = action.payload;
        state.isLoading = false;
      })
      .addCase(initializeUser.rejected, (state) => {
        state.isLoading = false;
      });
  }
});

export default userSlice.reducer;

3. 修改AuthProvider逻辑

等待加载状态完成后再判断用户是否登录,避免初始null值导致的错误跳转:

// auth provider
import React from "react";
import { useSelector } from "react-redux";
import { Navigate, useLocation } from "react-router-dom";

export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
  const { user: currentUser, isLoading } = useSelector((state) => state.userData);
  const location = useLocation();

  // 加载中时显示过渡UI,可替换为自定义加载组件
  if (isLoading) {
    return <div>加载中...</div>;
  }

  // 加载完成后,无用户则跳转登录页
  if (!currentUser) {
    return (
      <Navigate to="/signIn" replace state={{ path: location.pathname }} />
    );
  }

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

4. 在应用启动时触发初始化逻辑

在App组件中调用初始化Thunk,确保应用启动时校验登录状态:

// app.jsx
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { initializeUser } from './path/to/userSlice';

function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(initializeUser());
  }, [dispatch]);

  return (
    <div className="App grid">
      <AuthProvider>
         <Navbar />
         <Routes>
           <Route path="channels" element={<UserChannels />} />
           <Route path="/channel/new" element={<CreateChannel />} />
           <Route path="/channel/:channelID" element={<Channel />} />
         </Routes>
      </AuthProvider>
    </div>
  );
}

原理说明

通过添加isLoading状态,我们避免了组件挂载时直接使用Redux初始的null值判断登录状态,而是等待登录状态校验完成后再做路由跳转决策,确保已登录用户能正常访问受保护路由。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:05:32