自定义React-Admin应用中useNavigate()钩子使用异常问题
问题核心分析
你遇到的[Route] is not a <Route> component错误,本质是自定义登录组件MyLoginPage没有处于React-Admin内部的路由上下文环境中。虽然你把它传给了<Admin>的loginPage属性,但如果外层的Shell组件存在渲染逻辑问题,会导致MyLoginPage在<Admin>完成路由上下文初始化前就被渲染,或者直接脱离了<Admin>的路由树。
具体解决方案
1. 修正Shell组件的认证渲染逻辑
检查Shell组件的代码,确保它没有直接渲染MyLoginPage。正确的做法是:Shell只负责处理Firebase认证状态,并将认证结果传递给React-Admin的authProvider,由<Admin>根据认证状态自动渲染loginPage。
错误示例(可能存在的Shell逻辑):
// 错误:Shell直接渲染MyLoginPage,脱离Admin路由上下文 const Shell = ({ children }) => { const [isAuthenticated] = useAuthState(firebaseAuth); if (!isAuthenticated) { return <MyLoginPage />; // 这里直接渲染,不在Admin路由内 } return children; };
正确修正:
// 正确:Shell只传递认证状态,由Admin处理登录页渲染 const Shell = ({ children }) => { const [user, loading] = useAuthState(firebaseAuth); if (loading) return <div>Loading...</div>; // 将用户状态传递给Admin的authProvider或通过context传递 return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>; };
2. 使用React-Admin内置的useRedirect钩子替代useNavigate
React-Admin封装了自己的路由跳转钩子useRedirect,专门适配内部路由体系,无需依赖react-router的useNavigate,从根源避免路由上下文问题:
import { useRedirect, LoginForm } from 'react-admin'; const MyLoginPage = () => { const redirect = useRedirect(); const handleLogin = async (credentials) => { // 你的Firebase登录逻辑 await firebaseAuth.signInWithEmailAndPassword(credentials.email, credentials.password); // 登录成功后跳转至首页 redirect('/'); }; return <LoginForm onSubmit={handleLogin} />; };
3. 排查额外路由上下文冲突
再次确认Shell或其他外层组件没有嵌套额外的<BrowserRouter>/<HashRouter>。如果存在多个Router实例,会导致路由上下文混乱,useNavigate无法找到正确的上下文。
4. 确保Admin组件的路由初始化完成
如果上述方法都无效,可以尝试将MyLoginPage的渲染延迟到<Admin>完成路由初始化后。比如在MyLoginPage中添加路由上下文检查:
import { useNavigate, useLocation } from 'react-router-dom'; const MyLoginPage = () => { // 用useLocation触发路由上下文检查,避免提前渲染 useLocation(); const navigate = useNavigate(); // 其余逻辑 };
总结
最常见的原因是Shell组件直接渲染了MyLoginPage,导致它脱离了React-Admin的路由上下文。优先修正Shell的认证逻辑,改用React-Admin内置的useRedirect钩子,能快速解决问题。
内容的提问来源于stack exchange,提问作者Janus

