React 路由、鉴权以及网页标题
data Router
- react 路由有三种写法:传统组件法、useRoutes 法、data Router 法
- 官方推荐的写法是 data Router
- 这里用 data Router
- route 的 handle 类似 vue-router 中的 meta
- handle 属性仅在 data Router 下有效
- 获取 handle 的 useMatches 只能在 data Router 下调用
import { createBrowserRouter, Navigate } from "react-router-dom";
import { PageIndex } from "@/page";
export const router = createBrowserRouter([
{
path: "/",
element: <AuthRoute />,
children: [
{ path: "", element: <PageIndex />, handle: { title: "首页" } },
{ path: "login", element: <PageLogin />, handle: { title: "登录页" } },
{ path: "*", element: <Navigate to="404" replace /> },
{ path: "404", element: <Page404 />, handle: { title: "404页" } },
],
},
]);
import { RouterPrivider } from "react-router-dom";
import { router } from "./routes";
export function App() {
return <RouterProvider router={router} />;
}
鉴权 & 网页标题
- 所有路由变化都会触发 AuthRoute 的更新
- AuthRoute 返回的 JSX 就是路由的结果
function AuthRoute() {
const matches = useMatches();
const outlet = useOutlet();
const isLogined = useAppSelector((state) => state.auth.isLogined);
const page = useMemo(() => {
const { pathname } = matches[1];
const isInWL = whiteList.includes(pathname);
if (isInWL) return outlet;
if (isLogined) return outlet;
return <Navigate to="login" replace />;
}, [isLogined, matches, outlet]);
useEffect(() => {
const title = (matches[1].handle as any)?.title;
const isHasTitle = typeof title === "string";
if (isHasTitle) {
document.title = title;
}
}, [matches]);
return page;
}
懒加载
- vue-router 里的 component 可以直接写成一个回调实现懒加载
- 但是 react-router 没有,需要我们自己写 hook
import { Skeleton } from "antd";
import React from "react";
export namespace Type {
export type defRC = {
default: React.ComponentType<any>;
};
}
export function useLazy(callback: () => Promise<Type.defRC>) {
const LazyComp = React.lazy(callback);
return (
<React.Suspense fallback={<Skeleton active />}>
<LazyComp />
</React.Suspense>
);
}
import { Navigate, RouteObject } from "react-router-dom";
export const routes: RouteObject[] = [
{
path: "/home",
element: useLazy(() => import("@/page/home")),
},
];