ReactRouter6.0

281 阅读3分钟

ReactRouter6.0 安装使用

官网

官方英文文档:Feature Overview v6.10.0 | React Router

中文文档:www.reactrouter.cn/docs/gettin…

安装

# npm 安装
npm install react-router-dom
# yarn 安装
yarn add react-router-dom
# pnpm 安装
pnpm add react-router-dom

路由组件

BrowserRouter
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'

// 使用组件包裹
<BrowserRouter>
    <App />
</BrowserRouter>
Routes定义路由
<Routes>
   <Route path='/' element={<App />}></Route>
   <Route path='/demo' element={<React />}></Route>
</Routes>
组件定义
function React() {
  return <h2>欢迎学习React课程</h2>
}

路由跳转

官网

官方英文文档:Feature Overview v6.10.0 | React Router

中文文档:www.reactrouter.cn/docs/gettin…

使用

NavLink
<NavLink to="/react"></NavLink> 
Link
<Link to="/react"></Link> 
Navigate(重定向组件)
// 路由中使用
<Route path='/vite' element={<Navigate to={'/react'} />}></Route>

// 组件中使用
function Vue() {
  return <h2>欢迎学习Vue课程{<Navigate to={'/react'} />}</h2>
}
Hook - useNavigate
// 前提:必须在函数组件里面定义
const navigate = useNavigate();


// 点击按钮,进行跳转
navigate('/react')
404定义
<Route path='*' element={<NotFound />}></Route>

API创建路由(推荐方式)

useRoutes
function Router(){
  let element = useRoutes([
      {
        path: "/",
        element: <App />,
      },
      {
        path: "/vite",
        element: <Vite />,
      },
      {
        path: "/react",
        element: <ReactDemo />
      },
      {
        path: "*",
        element: <NotFound />
      },
  ]);
}
export default Router;

// 在main.tsx中加载
import BaseRouter from './router2'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <BrowserRouter>
    <BaseRouter />
  </BrowserRouter>
)
createBrowserRouter
import { createBrowserRouter, RouterProvider} from "react-router-dom";

// 创建路由
const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
  },
  {
    path: "/vite",
    element: <Vite />,
  },
  {
    path: "/react",
    element: <ReactDemo />
  },
  {
    path: "*",
    element: <NotFound />
  },
]);

// 传递给RouterProvider
<RouterProvider router={router} />
createHashRouter

用法同上。

动态路由、嵌套路由

basename

基础路由地址

{
    basename: '/app'
}
动态路由
{
    path: '/order/:orderId',
    element: <Order/>
}


{
    path: '/goods/:goodsId/order/:orderId',
    element: <Order/>
}


function Order(){
    const params = useParams();
    return <div>
        <h2>商品组件</h2>
        <p>
            <span>商品ID:{params.goodsId}</span>
            <span>订单ID:{params.orderId}</span>
        </p>
    </div>
}
嵌套路由
{
  path: '/goods',
  element: <Goods />,
  children: [
    {
      path: 'list',
      element: (
        <div>
          <p>商品一</p>
          <p>商品二</p>
        </div>
      )
    },
    {
      path: 'cart',
      element: (
        <div>
          <p>苹果手机,价格5999</p>
          <p>小米手机,价格2999</p>
        </div>
      )
    }
  ]
}

// 组件定义
function Goods() {
  return (
    <div>
      <h2>商品主页</h2>
      <Outlet />
    </div>
  )
}
两个知识点
  • useParams()

  • Outlet(相当于Vue里面的 组件)

5-6 Data API

前置条件

只有上面四个API创建的路由才有Data API功能

Loader、useLoaderData

数据加载器

{
      path: '/order/:id',
      element: <Order />,
	  loader: orderLoader
}


function orderLoader({ params }: any) {
  return params.id;
}


function orderLoader({ params }: any) {
  if (!sessionStorage.token) return redirect('/login')
  return {
    token: sessionStorage.token
  }
}


function orderLoader({ params }: any) {
  if (!sessionStorage.token) return redirect('/login')
  return fetch(`/${params.id}.json`)
}
Action、useActionData

reactrouter.com/en/main/hoo…

5-8 总结

前面七节课详细讲解了ReactRouter6.0的基础语法,我们在实战部分会深入使用。每节课的课程案例都创建对应的分支,大家可以克隆源码,切换分支查看。

路由安装

# npm 安装
npm install react-router-dom
# yarn 安装
yarn add react-router-dom
# pnpm 安装
pnpm add react-router-dom

路由组件

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'

// 使用组件包裹
<BrowserRouter>
    <Routes>
       <Route path='/' element={<App />}></Route>
       <Route path='/demo' element={<React />}></Route>
    </Routes>
</BrowserRouter>
注意,可以使用Hook简写
function Router(){
  let element = useRoutes([
      {
        path: "/",
        element: <App />,
      },
      {
        path: "/demo",
        element: <React />,
      }
  ]);
}
export default Router;

// 在main.tsx中加载
import Router from './router'
<BrowserRouter>
   <Router />
</BrowserRouter>

通过API创建路由

import { createBrowserRouter, RouterProvider} from "react-router-dom";

// 创建路由
const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
  },
  {
    path: "/demo",
    element: <React />,
  }]);

// 传递给RouterProvider
<RouterProvider router={router} />

动态路由

{
    path: '/order/:orderId',
    element: <Order/>
}


{
    path: '/goods/:goodsId/order/:orderId',
    element: <Order/>
}

function Order(){
    const params = useParams();
    return <div>
        <h2>商品组件</h2>
        <p>
            <span>商品ID:{params.goodsId}</span>
            <span>订单ID:{params.orderId}</span>
        </p>
    </div>
}

嵌套路由

{
  path: '/goods',
  element: <Goods />,
  children: [
    {
      path: 'list',
      element: (
        <div>
          <p>商品一</p>
          <p>商品二</p>
        </div>
      )
    }
  ]
}

// 组件定义
function Goods() {
  return (
    <div>
      <h2>商品主页</h2>
      <Outlet />
    </div>
  )
}

Data API

只有API创建的路由才有,组件创建的路由没有Data API

Loader拦截
{
      path: '/order/:id',
      element: <Order />,
      loader: orderLoader
}


function orderLoader({ params }: any) {
  return params.id;
}
Action提交
// 路由定义,定义action
{
    path: '/login',
    element: <Login />,
    action: loginAction
}


// 表单组件定义,提交以后,会触发action
function Login() {
  const errors: any = useActionData()
  return (
    <Form method='post'>
      <p>
        <input type='text' name='email' />
        {errors?.email && <span>{errors.email}</span>}
      </p>

      <p>
        <input type='text' name='password' />
        {errors?.password && <span>{errors.password}</span>}
      </p>

      <p>
        <button type='submit'>登录</button>
      </p>
    </Form>
  )
}


async function loginAction({ request }: any) {
  const formData = await request.formData()
  const email = formData.get('email')
  const password = formData.get('password')
  // TODO
  console.log('创建用户成功')
  return redirect('/')
}