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

使用RTK Query实现登录路由时遇组件错误及权限路由问题

问题详情
  • 基于RTK Query实现登录页面,配置了登录页与首页路由,通过isAuthenticated属性实现ProtectedRoute权限路由并应用于首页,同时向Login组件传递onLogin={handleLogin}回调
  • 当前存在两个问题:
    1. 控制台报错“Login不是组件”
    2. Login.js组件无法获取全局的isAuthenticated状态值
  • 预期实现效果:
    • 已处于首页时,无法返回登录页
    • 已登录状态下,禁止访问登录页

相关代码

Login.js

const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
useEffect(() => {
if (data?.response === "true" && data?.state === "success"){
setErrorMsg("");
setEmail("");
setPassword("");
setIsAuthenticated(true);
navigate("/home", { state: { user: data?.user } });
}
else if (data?.response === "false" && data.state === "error"){
  setErrorMsg(true);
}
  else{
    setErrorMsg(false)
  }
}, [data,isError,isLoading]);

const handleLogin = async (e) => {
e.preventDefault();
console.log("****")
await loginUser({email,password})

}

App.js

function App() {

const [isAuthenticated, setIsAuthenticated] = useState(false);
const handleLogin = () => {
setIsAuthenticated(true);
}

return (
<div className="App">
  <Router>
    <Routes>
      <Route exact path="/">
        <Login onLogin={handleLogin} />
      </Route>
      <ProtectedRoute path="/home" component={Home} isAuthenticated={isAuthenticated}/>
    </Routes>
  </Router>
</div>
);
}
export default App;

ProtectedRoute.js

import React from "react";
import { Route, Navigate } from "react-router-dom";

const ProtectedRoute = ({ isAuthenticated}) => {
return isAuthenticated? <Outlet /> : <Navigate to="/" />;
}

export default ProtectedRoute;

解决方案

1. 修复“Login不是组件”错误

react-router-dom v6中,<Route>组件不再支持直接嵌套子组件,必须通过element属性指定要渲染的组件。同时ProtectedRoute作为路由容器,需要嵌套子路由来渲染Home组件:

// 修改App.js中的路由配置
<Routes>
  {/* 用element属性传递Login组件 */}
  <Route path="/" element={<Login onLogin={handleLogin} isAuthenticated={isAuthenticated} />} />
  {/* ProtectedRoute作为父路由,内部用index路由渲染Home */}
  <Route path="/home" element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
    <Route index element={<Home />} />
  </Route>
</Routes>

2. 让Login.js获取全局isAuthenticated状态

将App中维护的isAuthenticated和onLogin通过props传递给Login组件,同时移除Login内部的setIsAuthenticated,统一通过父组件回调更新全局状态:

// 修改Login.js,接收props参数
const Login = ({ isAuthenticated, onLogin }) => {
  const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
  const navigate = useNavigate();
  // 其他内部状态(errorMsg、email、password)保持不变

  useEffect(() => {
    if (data?.response === "true" && data?.state === "success") {
      setErrorMsg("");
      setEmail("");
      setPassword("");
      // 调用父组件的onLogin更新全局登录状态
      onLogin();
      navigate("/home", { state: { user: data?.user } });
    } else if (data?.response === "false" && data.state === "error") {
      setErrorMsg(true);
    } else {
      setErrorMsg(false);
    }
  }, [data, isError, isLoading, onLogin, navigate]);

  // handleLogin逻辑保持不变
}

3. 实现登录状态下禁止访问登录页

在Login组件中添加状态检查,若已登录则自动跳转到首页:

// 在Login组件中添加
useEffect(() => {
  if (isAuthenticated) {
    navigate("/home", { replace: true });
  }
}, [isAuthenticated, navigate]);

4. 完善ProtectedRoute逻辑

确保ProtectedRoute正确使用Outlet渲染子路由,并且添加replace属性避免跳转后留下历史记录:

// 修改ProtectedRoute.js
import React from "react";
import { Navigate, Outlet } from "react-router-dom";

const ProtectedRoute = ({ isAuthenticated }) => {
  return isAuthenticated ? <Outlet /> : <Navigate to="/" replace />;
};

export default ProtectedRoute;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:13:23