路由守卫,一个做权限拦截等功能的好地方,在 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>,
);