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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:05:25