React-Admin中如何创建无需认证的路由?
我明白你的困扰——明明把路由放在了Admin组件外面,结果还是触发了checkAuth跳转到登录页。这大概率是两个原因:要么你的AddRecipients组件依赖了React-Admin的上下文(比如用了useDataProvider这类钩子),要么你的路由配置方式不对,导致Admin的认证逻辑还是覆盖到了这个路由。下面给你两种针对性的解决方案:
方案一:路由完全独立(不依赖React-Admin上下文)
如果你的AddRecipients组件不需要用React-Admin的任何工具(比如数据提供者、权限钩子),那可以把这个路由完全抽离到Admin的路由范围之外。调整你的路由结构,用react-router-dom的Routes把无认证路由和Admin路由并列:
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { Admin, Resource } from 'react-admin'; import AddRecipients from './path/to/AddRecipients'; // 导入你的其他组件和资源配置 function App() { return ( <BrowserRouter> <Routes> {/* 把无认证路由放在最前面,优先匹配 */} <Route path="/products/:slug" element={<AddRecipients />} /> {/* Admin的所有路由作为一个兜底路由 */} <Route path="/*" element={ <Admin dataProvider={DataProvider} authProvider={authProvider}> <Resource name="users" list={UsersList} show={UsersShow} edit={UsersEdit} create={UsersCreate} icon={PeopleIcon} /> <Resource name="candidatures" list={CandidaturesList} show={CandidaturesShow} edit={CandidaturesEdit} create={CandidaturesCreate} icon={NoteAltIcon} /> {/* ...你的其他资源 */} </Admin> } /> </Routes> </BrowserRouter> ); }
这样访问/products/:slug时,会直接渲染AddRecipients,完全不经过Admin的认证拦截。但要注意,这个组件里不能用任何React-Admin的上下文钩子,否则会报错。
方案二:路由在Admin内部(依赖React-Admin上下文)
如果你的AddRecipients需要用React-Admin的功能(比如调用dataProvider),那得把路由放在Admin的CustomRoutes里,然后通过两种方式跳过认证:
方式A:用React-Admin的UnprotectedRoute组件(推荐,v4+可用)
React-Admin v4提供了专门的UnprotectedRoute组件,能直接让路由跳过认证检查,不用改authProvider:
import { UnprotectedRoute } from 'react-admin'; <Admin dataProvider={DataProvider} authProvider={authProvider}> <CustomRoutes> {/* 用UnprotectedRoute替换原来的Route */} <UnprotectedRoute path="/products/:slug" element={<AddRecipients />} /> </CustomRoutes> {/* 你的资源配置 */} <Resource name="users" list={UsersList} ... /> </Admin>
方式B:修改authProvider的checkAuth逻辑
如果你的React-Admin版本比较旧,没有UnprotectedRoute,可以直接在checkAuth里判断当前路由,跳过认证:
const authProvider = { checkAuth: () => { const currentPath = window.location.pathname; // 匹配/products/开头的路由,直接返回成功 if (currentPath.startsWith('/products/')) { return Promise.resolve(); } // 其他路由正常检查认证 const token = localStorage.getItem('你的token键名'); if (token) { return Promise.resolve(); } // 无token则跳登录 return Promise.reject(); }, // ...其他authProvider方法(比如login、logout等) };
然后保持你原来的CustomRoutes配置就行,访问/products/:slug时,checkAuth会直接通过,不会跳登录。
你可以根据自己的组件需求选其中一种方案试试,应该就能解决问题啦!
备注:内容来源于stack exchange,提问作者Lebonsavane

