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

React中react-router与useNavigate登录后跳转首页失效问题

登录后无法自动跳转首页问题排查与修复

问题说明

登录成功后页面仅刷新,无法自动跳转至首页,手动访问首页功能正常;跳转其他页面(如/register)功能正常。预期效果为:登录成功后自动跳转到首页,登录接口返回数据存储在currentUser变量中,当currentUser有效时允许访问首页。

核心原因分析

  1. AuthContext中useEffect依赖错误
    原代码中useEffect依赖了login函数,组件每次渲染时login都会被重新创建,导致useEffect频繁触发,可能在currentUser未完全更新时就执行localStorage.setItem,干扰状态同步逻辑。

  2. ProtectedRoute状态感知不及时
    App组件中直接获取currentUser并定义ProtectedRoute,当currentUser更新时,ProtectedRoute无法实时获取最新状态,导致跳转首页时仍判定用户未登录,触发重定向回/login,造成页面刷新的假象。

  3. 登录函数错误处理缺失
    login函数未处理请求失败场景,若接口返回错误,currentUser未被正确设置,但handleLogin仍会执行navigate("/"),此时ProtectedRoute因currentUser为null触发重定向。

修复方案

1. 修正AuthContextProvider的useEffect依赖

移除login作为useEffect的依赖,仅保留currentUser,并增加空值判断避免无效存储:

export const AuthContextProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(
    JSON.parse(localStorage.getItem("users")) || null
  );

  const login = async (inputs) => {
    try {
      const res = await axios.post("https://micacarballo-social-media-api.onrender.com/api/v1/auth/login", inputs);
      setCurrentUser(res.data);
      return res.data;
    } catch (err) {
      throw err;
    }
  };

  useEffect(() => {
    if (currentUser) {
      localStorage.setItem("users", JSON.stringify(currentUser));
    }
  }, [currentUser]);
 
  const updateUser = async () =>{
    const user = JSON.parse(localStorage.getItem("users"));
    if (!user?.token) return;
    const res = await axios.get("https://micacarballo-social-media-api.onrender.com/api/v1/users/me/",{
      headers: {
        Authorization: `jwt ${user.token}`
      }
    });
    setCurrentUser(res.data);
  };

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

2. 重构ProtectedRoute为独立组件

将ProtectedRoute抽离为独立组件,确保每次渲染都能获取最新的currentUser:

// 单独创建ProtectedRoute.js文件
import { AuthContext } from './context/authContext';
import { Navigate } from 'react-router-dom';

export const ProtectedRoute = ({ children }) => {
  const { currentUser } = useContext(AuthContext);
  
  if (!currentUser) {
    return <Navigate to="/login" replace />;
  }
  
  return children;
};

然后在App组件中使用该组件:

import { ProtectedRoute } from './ProtectedRoute';
import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';

function App() {
  const Layout = () => {
    return(
      <div>
        <Navbar />
        <div style={{ display: "flex" }}>
          <LeftBar />
          <div style={{ flex: 6 }}>
            <Outlet />
          </div>
        </div>
      </div>
    )
  };

  const router = createBrowserRouter([
    {
      path: "/",
      element: (
        <ProtectedRoute>
          <Layout/>
        </ProtectedRoute>
      ),
      children :[
        { path:"/", element: <Home /> },
        { path:"/profile/:id", element:<Profile /> }
      ]
    }, 
    { path: "/login", element: <Login /> },
    { path: "/register", element: <Register /> }
  ]);

  return (
    <div className="App">
      <RouterProvider router={router} />
    </div>
  )
}

export default App

3. 确保AuthContextProvider正确包裹应用入口

在index.js中确认AuthContextProvider包裹了App组件,保证全局状态可被路由组件访问:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { AuthContextProvider } from './context/authContext';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <AuthContextProvider>
    <App />
  </AuthContextProvider>
);

验证逻辑

登录成功后,login函数会正确设置currentUser并返回数据,handleLogin中await login(inputs)确保状态更新完成后再执行navigate("/");ProtectedRoute实时获取最新的currentUser,允许访问首页,不会触发重定向。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:13:10