如何在React函数组件外使用useSelector Hook?路由鉴权需求问询
基于Redux状态控制React Router路由渲染的解决方案
我将项目路由拆分至routes.js文件,希望通过useSelector获取state.user.isAdmin判断是否为管理员,从而控制/admin路由渲染<Admin>或<Error>组件,但React Hooks仅能在函数组件或自定义Hook中调用,无法直接在routes.js中使用useSelector,现有代码如下:
现有代码
App.js
import { router } from '~/routes/Routes'; function App() { return ( <div className="App"> <RouterProvider router={router} /> </div> ); }
routes.js(不可行写法)
// can not use useSelector hook like this const isAdmin = useSelector((state) => state.user.isAdmin); export const router = createBrowserRouter([ { path: '/admin', element: isAdmin ? <Admin /> : <Error />, errorElement: <Error />, }, ]);
可行实现方案
方案一:创建权限控制组件(推荐)
单独编写一个权限校验组件,在组件内部使用useSelector,符合Hooks使用规则:
// components/RequireAdmin.js import { useSelector } from 'react-redux'; import { Error } from './Error'; export function RequireAdmin({ children }) { const isAdmin = useSelector((state) => state.user.isAdmin); if (!isAdmin) { return <Error />; } return children; }
修改routes.js,用该组件包裹<Admin>:
// routes.js import { createBrowserRouter } from 'react-router-dom'; import { Admin } from '../components/Admin'; import { Error } from '../components/Error'; import { RequireAdmin } from '../components/RequireAdmin'; export const router = createBrowserRouter([ { path: '/admin', element: ( <RequireAdmin> <Admin /> </RequireAdmin> ), errorElement: <Error />, }, ]);
当用户访问/admin时,RequireAdmin会先校验管理员状态,再决定渲染对应组件,状态更新时会自动重新渲染。
方案二:在Admin组件内部做权限判断
直接在<Admin>组件内部添加权限校验逻辑,无需额外组件:
// components/Admin.js import { useSelector } from 'react-redux'; import { Error } from './Error'; export function Admin() { const isAdmin = useSelector((state) => state.user.isAdmin); if (!isAdmin) { return <Error />; } // 管理员页面核心内容 return ( <div>Admin Dashboard</div> ); }
routes.js可直接简化为:
// routes.js import { createBrowserRouter } from 'react-router-dom'; import { Admin } from '../components/Admin'; import { Error } from '../components/Error'; export const router = createBrowserRouter([ { path: '/admin', element: <Admin />, errorElement: <Error />, }, ]);
方案三:使用React Router的loader函数(预加载校验)
如果需要在路由加载前就完成权限校验,可结合Redux Store实例直接访问状态(注意此方法不会自动监听状态变化,状态更新后需手动刷新路由):
首先确保导出Redux Store实例:
// store.js import { configureStore } from '@reduxjs/toolkit'; import userReducer from './features/user/userSlice'; export const store = configureStore({ reducer: { user: userReducer, }, });
然后在routes.js中使用loader:
// routes.js import { createBrowserRouter, redirect } from 'react-router-dom'; import { Admin } from '../components/Admin'; import { Error } from '../components/Error'; import { store } from '../store'; export const router = createBrowserRouter([ { path: '/admin', element: <Admin />, errorElement: <Error />, loader: () => { const isAdmin = store.getState().user.isAdmin; if (!isAdmin) { return redirect('/'); // 或重定向到错误页面 } return null; }, }, ]);
内容的提问来源于stack exchange,提问作者Quan Phung
相关产品推荐
相关产品推荐

