react-router-dom(6.18.0)最新指南

react-router-dom v6相比于v5变动很大,单独列出变动点觉得没有必要,可以当成全新的插件去学习并使用。官方文档的内容太多,这里整理一些平时常用的,降低入门门槛。

前提:使用 vite 新建React项目(后面我会出个相关教程的文章)

一、安装

csharp 复制代码
yarn add react-router-dom

目前版本:"react-router-dom": "^6.18.0"

二、基本使用

新建pages/login.tsx

javascript 复制代码
const Login = () => {
  return <div>登录页</div>;
};

export default Login;

新建pages/home.tsx

javascript 复制代码
const Home = () => {
  return <div>home页</div>;
};
export default Home;

1. 定义路由

新建router/routes.tsx

javascript 复制代码
/* eslint-disable react-refresh/only-export-components */
import { lazy } from 'react';

const Login = lazy(() => import('../pages/login'));
const Home = lazy(() => import('../pages/home'));

const routes = [
  {
    path: '/login',
    element: <Login />,
  },
  {
    path: '/',
    element: <Home />,
  },
];

export default routes;

新建router/index.tsx

javascript 复制代码
import { createBrowserRouter } from 'react-router-dom';

import routes from './routes';

//可传第二个参数,配置base路径 { basename: "/app"}
const router = createBrowserRouter(routes);

export default router;

2. 使用路由

修改入口main.tsx

javascript 复制代码
import { Suspense } from 'react';
import { RouterProvider } from 'react-router-dom';

import ReactDOM from 'react-dom/client';

import router from './router';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);

root.render(
  <Suspense fallback={<div>Loading...</div>}>
    <RouterProvider router={router} />
  </Suspense>,
);

在Suspense组件中渲染lazy组件,Suspense组件置于懒加载组件之上的任何位置;如果有嵌套路由,则需再使用Suspense组件包裹

三、嵌套路由

新建pages/user.tsx

javascript 复制代码
const User = () => {
  return <div>用户页</div>;
};

export default User;

新建pages/manage.tsx

javascript 复制代码
const Manage = () => {
  return <div>管理页</div>;
};

export default Manage;

1. 定义路由

修改router/routes.tsx

javascript 复制代码
//新增
const User = lazy(() => import('../pages/user'));

const Manage = lazy(() => import('../pages/manage'));

//修改
const routes = [
  {
    path: '/login',
    element: <Login />,
  },
  {
    element: <Home />,
    children: [
      {
        path: '/',
        element: <User />,
      },
      {
        path: '/manage',
        element: <Manage />,
      },
    ],
  },
];

2. 配置嵌套路由路口

  1. 安装styled-components,一个针对React的CSS-in-JS库,用来编写组件样式
csharp 复制代码
yarn add styled-components
  1. 修改pages/home.tsx
javascript 复制代码
import { Suspense } from 'react';
import { Outlet, NavLink } from 'react-router-dom';

import styled from 'styled-components';

const Home = () => {
  return (
    <Wrapper>
      <div className="header"></div>
      <div className="main">
        <aside>
          <div className="menu_item">
            <NavLink to="/" end>
              user
            </NavLink>
          </div>
          <div className="menu_item">
            <NavLink to="/manage" end>
              manage
            </NavLink>
          </div>
        </aside>
        <section>
          <Suspense fallback={<div>Loading...</div>}>
            <Outlet />
          </Suspense>
        </section>
      </div>
    </Wrapper>
  );
};

export default Home;

const Wrapper = styled.div`
  .header {
    height: 60px;
    border: 1px solid;
  }
  .main {
    height: calc(100vh - 60px);
    display: flex;
    aside {
      width: 260px;
      border: 1px solid;
      .active {
        color: red;
      }
    }
    section {
      flex: 1;
    }
  }
`;

Outlet组件呈现匹配的子路由,类似vue的router-view组件

四、配置404页面

修改router/routes.tsx

javascript 复制代码
const routes = [
  //...
  {
    path: '*',
    element: <div>404</div>,
  },
]

404路由放在路由配置表的最后

五、声明式、编程式导航

1. 声明式导航

pages/home.tsx

ini 复制代码
<NavLink to="/manage" end>manage</NavLink>

激活时,默认类名为active。end表示精准匹配,否则当访问/manage/123时,类名也为active

2. 编程式导航

修改pages/user.tsx

javascript 复制代码
import { useNavigate } from 'react-router-dom';

const User = () => {
  const navigation = useNavigate();
  return (
    <div>
      user
      <button onClick={() => navigation('/manage')}>manage</button>
    </div>
  );
};

export default User;

六、路由传参

新建pages/file.tsx

arduino 复制代码
const File = () => {
  return <div>File</div>;
};

export default File;

1. 动态路由匹配

  1. 定义动态路由

修改router/routes.tsx

javascript 复制代码
 //新增
const File = lazy(() => import('../pages/file'));

const routes = [
  //...
  {
    element: <Home />,
    children: [
      //...
      //新增
      {
        path: '/file/:id?',
        element: <File />,
      },
    ],
  },
];
  1. 定义路由跳转

修改pages/home.tsx

ini 复制代码
  <NavLink to="/file/123" end>
    file
  </NavLink>
  1. 获取参数

修改pages/file.tsx

javascript 复制代码
import { useParams } from 'react-router-dom';
const File = () => {
  const { id } = useParams();
  return <div>{id}</div>;
};

export default File;

2. search传参

1.定义路由

修改router/index.tsx

arduino 复制代码
{
  path: "/file",
  element: <File />,
},
  1. 编程式传参
xml 复制代码
  <NavLink to={{ pathname: '/file', search: '?sort=name&id=2' }} end>
    file
  </NavLink>
  1. 命令式传参
css 复制代码
<button onClick={() => navigation({ pathname: '/file', search: '?sort=name&id=2' })}>file</button>
  1. 获取参数
dart 复制代码
import { useSearchParams } from 'react-router-dom';
const File = () => {
  const [searchParams] = useSearchParams();
  return (
    <div>
      获取id:{searchParams.get('id')}
      获取sort:{searchParams.get('sort')}
    </div>
  );
};

export default File;

3. state传参

1.定义路由

arduino 复制代码
{
  path: "/file",
  element: <File />,
},
  1. 编程式传参
xml 复制代码
<NavLink to="/file" state={{ id: 1 }} end>  file</NavLink>
  1. 命令式传参
css 复制代码
<button onClick={() => navigation("/file", { state: { id: "2" } })}>  file</button>
  1. 获取参数
javascript 复制代码
import { useLocation } from "react-router-dom";
const File = () => {
  const { state } = useLocation();
  return <div>{state.id}</div>;
};

export default File;

特点:参数不会显示在路径上

七、错误处理

在路由组件加载过程中发生错误时展示的元素

  1. 新建pages/errorBoundary.tsx
javascript 复制代码
import { useRouteError } from 'react-router-dom';

const ErrorBoundary = () => {
  const error = useRouteError();
  //错误信息,可用来错误上报
  console.log(error);
  return <>错误页面</>;
};

export default ErrorBoundary;
  1. 修改router/index.tsx
javascript 复制代码
import ErrorBoundary from "../pages/errorBoundary";

const routes = [
  //...
  {
    element: <Home />,
    errorElement: <ErrorBoundary />, //挂载到父路由上
  },
]
  1. 修改pages/router.tsx,使其报错
typescript 复制代码
import { useNavigate } from "react-router-dom";

const obj: any = {
  a: "2",
};

const User = () => {
  const navigation = useNavigate();
  return (
    <div>
      {/* 报错:因为取不到c属性 */}
      {obj.b.c}
      user
      <button onClick={() => navigation("/manage")}>manage</button>
    </div>
  );
};

export default User;

访问/user时,可以看到原先的user页面内容被替换为错误页面

提示:如果路由没有配置errorElement,则错误将冒泡到最近的父路由上

八、重定向

情景:当没有权限时,重定向到登录页

修改pages/manage.tsx

javascript 复制代码
import { Navigate } from 'react-router-dom';

const Manage = () => {
  if (!localStorage.getItem('token')) {
    return <Navigate to="/login" replace={true} />;
  }

  return <div>manage</div>;
};

export default Manage;

replace={true}:进行重定向

九、loader,action

loader:在路由导航完成之前执行,类似于vue router的路由前置守卫

action:使用react-router-dom提供的Form表单,当表单提交时action会被触发

loader与action都是V6版本新增的内容,实际使用场景并不多,这里不再详细阐述。

相关推荐
y先森2 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy2 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz5 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇5 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒5 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员5 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐6 小时前
前端图像处理(一)
前端