react-router的基础用法

120 阅读6分钟

插件安装

npm add react-router-dom

react-router-dom:主要用于在 Web 应用中实现路由功能,提供了如 BrowserRouterLinkRoute 等与浏览器环境相关的组件和功能。

react-router-native:用于 React Native 应用的路由,与 react-router-dom 类似,但针对移动应用场景进行了适配和调整。

基础示例

创建app1和app2两个组件, 通过路由来控制切换

import {createBrowserRouter, RouterProvider} from 'react-router-dom'

const App1 = () => <div>this is app1</div>
const App2 = () => <div>this is app2</div>

const router = createBrowserRouter([
  {
    path: '/app1',
    element: <App1 />
  },
  {
    path: '/app2',
    element: <App2 />
  }
])

export default () => {
  return (
      <RouterProvider router={router}></RouterProvider>
  )
}

使用 createBrowserRouter 函数来创建一个路由配置对象 router,然后使用 RouterProvider 组件将这个配置对象提供给整个应用程序。

补充

createBrowserRoutercreateHashRouter 都是 React Router 库中的函数,用于创建不同类型的路由器实例。它们之间的主要区别在于它们管理 URL 的方式。

createBrowserRouter: createBrowserRouter 使用 HTML5 的 history API 来管理 URL。这意味着当用户在应用中导航时,URL 会被更新,并且用户可以使用浏览器的前进和后退按钮来导航历史记录。这种方式提供了一个更友好的用户体验,并且对 SEO 也更友好。它适用于大多数现代 Web 应用。

createHashRouter: createHashRouter 使用 URL 的 hash 部分(# 后面的部分)来管理路由。这意味着 URL 的改变不会导致页面刷新,因为 hash 的改变不会被服务器识别。这种方式在一些特定场景下有用,比如需要支持旧版浏览器,或者在开发过程中需要避免服务器配置的复杂性。但是,它对 SEO 不友好,因为搜索引擎通常不会索引 # 后面的内容。

项目结构

上面是路由的简单也是最基础的使用方式, 一般在项目中我们会创建单独的文件夹来管理所有的路由相关的操作

 src
   ├── pages
   |  ├── App1
   |  └── App2
   └── router
      └── index
   
  1. pages目录存放页面
  2. router 目录下存放路由相关

我们按照你这个结构把上面的事例拆分一下

import { createBrowserRouter } from "react-router-dom";
import App1 from "../pages/App1/index";
import App2 from "../pages/App2/index";

const router = createBrowserRouter([
    {
        path: "/",
        element: <App1 />
    },
    {
        path: "/app2",
        element: <App2 />
    }
])

export default router;
 const  App1 = () => {
  return (
    <div>
      <h1>App1</h1>
    </div>
  )
}

export default App1

上面我们分别定义了router.tsx和页面app1, app2与app1相同。 但同时我们还需要到入口处进行路由的引用改造。

import React from 'react';
import ReactDOM from 'react-dom/client';
import router from './router';
import { RouterProvider } from 'react-router-dom'

const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(
  <React.StrictMode>
    <RouterProvider router={router}></RouterProvider>
  </React.StrictMode>,
);

嵌套

还是上面的示例, 现在在app1这个页面, 嵌入app3. 我们先去router列表路面嵌套

import { createBrowserRouter } from "react-router-dom";
import App1 from "../pages/App1/index";
import App2 from "../pages/App2/index";
import App3 from "../pages/App3/index";

const router = createBrowserRouter([
    {
        path: "/",
        element: <App1 />,
        children: [
            {
                path: 'app3',
                element: <App3 />
            }
        ]
    },
    {
        path: "/app2",
        element: <App2 />
    }
])

export default router;

然后在app1 页面提供路由的出口

import { Outlet } from 'react-router-dom'

const  App1 = () => {
  return (
    <div>
      <h1>App1</h1>
      <Outlet />
    </div>
  )
}

export default App1

根据router我们的访问地址应该是http://127.0.0.1:3000/app3

路由导航

上面路由通过手动在地址栏切换已经可以看到效果, 但一般我们在系统内进行切换,,都是通过导航交互进行的

导航链接

import { Outlet, Link } from 'react-router-dom'

const  App1 = () => {
  return (
    <div>
      <h1>App1</h1>
      <Link to="/app3">to app3</Link>
      <Outlet />
    </div>
  )
}

export default App1

<Link>组件用于在React应用中创建导航链接,允许用户在不同的路由之间导航。

Link组件的to属性,用于指定用户点击链接时应导航到的路径。在这个例子中,/app3代表应用程序中的一个特定路径。

此外,<Link>组件还提供了replacestate等其他属性

编程式导航

import { useNavigate } from 'react-router-dom'

const  App3 = () => {
  const navigate = useNavigate()
  return (
    <div>
      <h1 onClick={() => navigate('/app2') }>App3</h1>
    </div>
  )
}
export default App3

useNavigatereact-router-dom 库提供的一个钩子(hook),它允许你在组件中编程式地导航到不同的路由。当你调用 useNavigate() 时,它会返回一个函数,你可以使用这个函数来导航到应用中的不同页面或路径。

传参

方式一

传递

<Link to="/app3?id=101&name=zhangsan">to app3</Link>

接收

import { useNavigate, useSearchParams } from 'react-router-dom'

const  App3 = () => {
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()
  const id = searchParams.get('id')
  const name = searchParams.get('name')
  return (
    <div>
      <h1 onClick={() => navigate('/app2') }>App3</h1>
      <span>id: {id}</span>
      <span>name: { name }</span>
    </div>
  )
}
export default App3

调用 useSearchParams 用来获取当前 URL 的查询参数。该函数会返回一个包含所有查询参数的对象,searchParams 以及一个可以用来设置查询参数的函数 setSearchParams。这样,组件就可以读取 URL 中传递的查询参数,也可以通过 setSearchParams 函数修改这些参数,从而实现更新 URL,并在应用中导航到新的路径或状态。

setSearchParams 函数的使用可能稍微复杂一些,因为它需要一个新的查询参数字符串或者一个对象来表示新的参数。在设置参数时,你可以传递整个字符串:

setSearchParams('?id=101&name=zhangsan');:或者一个对象

setSearchParams({
  id: '101',
  name: 'zhangsan'
});

例如,在点击事件处理程序中,你可以使用 setSearchParams 函数导航到 App2 并传递新的查询参数:

import { useNavigate, useSearchParams } from'react-router-dom';

const App3 = () => {
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  const handleClick = () => {
    setSearchParams({
     id: '101',
     name: 'zhangsan'
    });
    navigate('/app2');
  };

  return (
    <div>
      <h1 onClick={handleClick}>App3</h1>
    </div>
  );
};

export default App3;

在这个例子中,当用户点击 App3 标题时,handleClick 函数会被调用。它会先设置查询参数,然后使用 navigate 函数导航到 /app2 路径。App2 组件可以通过 useSearchParams 获取设置的查询参数。

方式二

传递

<Link to="/app2/101/zhangsan">to app2</Link>

这种方式我们还需要修改一下路由

{
        path: "/app2/:id/:name",
        element: <App2 />
    }

接收

import { useParams } from 'react-router-dom'

const  App2 = () => {
  const params = useParams()
  return (
    <div>
      <h1>App2</h1>
      <span>id: {params.id }</span>
      <span>name: { params.name }</span>
    </div>
  )
}
export default App2

对比

useParamsuseSearchParams 是两个不同的获取参数的钩子,它们用于从当前的 URL 中提取不同类型的信息:

useParams: useParams 钩子用于获取 URL 中的路由参数。当你在 React Router 中定义了路由配置,并在路径中使用了参数化的语法,比如 /user/:id,你可以使用 useParams 来获取 id 的值。这个钩子返回一个对象,其中包含了所有路由参数的键值对。例如,在 /user/123 的 URL 中,useParams 将返回 { id: '123' }

useSearchParams: useSearchParams 钩子用于获取 URL 中的查询参数。查询参数是在 URL 问号后面的部分,通常用于传递额外的信息,比如筛选条件、排序方式等。useSearchParams 返回一个包含所有查询参数的数组。每个参数都是一个包含 namevalue 键的对象。例如,在 ?id=101&name=zhangsan 的 URL 中,useSearchParams 将返回一个包含两个对象的数组:[{ name: 'id', value: '101' }, { name: 'name', value: 'zhangsan' }]。 与 useParams 不同,useSearchParams 还提供了一个函数 setSearchParams,允许你通过编程方式设置查询参数,从而改变 URL。