使用RTK Query实现登录路由时遇组件错误及权限路由问题
问题详情
- 基于RTK Query实现登录页面,配置了登录页与首页路由,通过
isAuthenticated属性实现ProtectedRoute权限路由并应用于首页,同时向Login组件传递onLogin={handleLogin}回调 - 当前存在两个问题:
- 控制台报错“Login不是组件”
- 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
相关产品推荐
相关产品推荐

