# vite-react
**Repository Path**: arilswei/vite-react
## Basic Information
- **Project Name**: vite-react
- **Description**: 基于 vite 的 React18 项目,路由方案:react-router-dom@6,全局状态:@reactjs/tookit
- **Primary Language**: TypeScript
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-02-22
- **Last Updated**: 2023-02-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 2023:React 路由鉴权、随路由修改网页标题
## data Router
1. react 路由有三种写法:传统组件法、useRoutes 法、data Router 法
2. 官方推荐的写法是 data Router
3. 这里用 data Router
4. route 的 handle 类似 vue-router 中的 meta
5. handle 属性仅在 data Router 下有效
6. 获取 handle 的 useMatches 只能在 data Router 下调用
```tsx
// routes.tsx
import { createBrowserRouter, Navigate } from "react-router-dom";
import { PageIndex } from "@/page";
export const router = createBrowserRouter([
{
// 确保所有的路由都走 AuthRoute 组件
path: "/",
// 这个组件做鉴权和处理标题
element: ,
// 真正的网页
children: [
{ path: "", element: , handle: { title: "首页" } },
{ path: "login", element: , handle: { title: "登录页" } },
// 没有匹配到的路由重定向到 404
{ path: "*", element: },
{ path: "404", element: , handle: { title: "404页" } },
],
},
]);
// App.jsx
import { RouterPrivider } from "react-router-dom";
import { router } from "./routes";
export function App() {
return ;
}
```
## 鉴权 & 网页标题
1. 所有路由变化都会触发 AuthRoute 的更新
2. 通过 AuthRoute 返回值控制路由的结果
```tsx
// route/index.ts
/**
* 实现路由鉴权,并根据路由修改网页标题
* @returns 通过时为 page,反之 PageLogin
*/
function AuthRoute() {
/**
* 1.获取路由匹配信息
* 2.获取子路由 JSX
* 3.获取 store 中的登录信息
*/
const matches = useMatches(); //这个钩子只有 data Router 下能用
const outlet = useOutlet();
const isLogined = useAppSelector((state) => state.auth.isLogined);
/**
* 当前路径是否在白名单?
* 当前是否已登录?
* 都不是则重向定到 PageLogin
*/
const page = useMemo(() => {
const { pathname } = matches[1];
const isInWL = whiteList.includes(pathname);
if (isInWL) return outlet;
if (isLogined) return outlet;
return ;
}, [isLogined, matches, outlet]);
/**
* 模仿 vue-router 后置钩子修改网页标题
*/
useEffect(() => {
const title = (matches[1].handle as any)?.title;
const isHasTitle = typeof title === "string";
if (isHasTitle) {
document.title = title;
}
}, [matches]);
return page;
}
```
## 懒加载
1. vue-router 里的 component 可以直接写成一个回调实现懒加载
2. 但是 react-router 没有,需要我们自己写 hook
```tsx
// useLazy.tsx
import { Skeleton } from "antd";
import React from "react";
/**
* @function useResize 使用的类型
*/
export namespace Type {
export type defRC = {
default: React.ComponentType;
};
}
/**
* 类似 React.lazy,实现组件懒加载
* @param callback 返回 Promise 的函数
* @returns JSX
*/
export function useLazy(callback: () => Promise) {
const LazyRC = React.lazy(callback);
return (
}>
);
}
```
- 用上 hook 后,route 的写法
```tsx
// routes.tsx
import { Navigate, RouteObject } from "react-router-dom";
export const routes: RouteObject[] = [
{
path: "/home",
element: useLazy(() => import("@/page/home")),
},
];
```