在 react-router-dom v6 中实现路由守卫

1,269 阅读1分钟

路由守卫,一个做权限拦截等功能的好地方,在 react-router-dom v6 中如何实现呢,重要的是在合适的位置,插入路由守卫,同时这个路由守卫里面可以访问 redux,以及和 URL 路由相关的 hook。目前两种办法:

根组件

设置一个根组件 <App />,把路由放在这个组件里面。

root.render(
  <React.StrictMode>
    <ThemeContextProvider>
      <Provider store={store}>
        <App />
      </Provider>
    </ThemeContextProvider>
  </React.StrictMode>
);

接下来在这个组件里面放置路由:

const App = () => {
  const dispatch = useDispatch();
  const routes = useSelector(.....);

  useEffect(() => {
    dispatch(fetchRoutes());
  }, [dispatch]);

  const router = useMemo(() => {
    if (routes) {
      return createBrowserRouter(routes);
    }
    return null;
  }, [routes]);

  return router
    ? <RouterProvider router={router} />
    : (
      ... loading UI/UX ...
    );
};

这种办法是直接在组件内使用,一般用 react-router-dom v5 就这么干,主要是灵活 v6 也可以这么做。

根路由

v6 可以使用 createBrowserRouter 创建 API 管理的路由,我们通过 hack 的办法设置一个根路由:

export function getRouter(store: Store) {
    return createBrowserRouter([
        {
            path: "/",
            element: createRouterGuards(store),
            children: routeModuleList,
        },
    ]);
}

访问所有的路由,都会经过这个根路由,原理基本和根组件相同,getRouter 里面的根路由使用了 element,我们要想获取 store 就只能通过函数传递。

root.render(
    <StrictMode>
        <Provider store={store}>
            <RouterProvider router={getRouter(store)} />
        </Provider>
    </StrictMode>,
);

但是 element 里面不能使用 hook,所以最好的办法还是使用组件,以下是新的代码:

export const router = createBrowserRouter([
	{
		path: "/",
		Component: createRouterGuards,
		children: routeModuleList,
	},
]);

root.render(
    <StrictMode>
        <Provider store={store}>
            <RouterProvider router={router} />
        </Provider>
    </StrictMode>,
);

参考