一篇文章了解 ReactRouter

0 阅读4分钟

v5

简介

React Router v5 是 React 生态中较早期的路由方案,虽然目前已被 v6 取代,但在许多遗留项目或旧项目中仍被使用。以下是 React Router v5 的基本用法和核心概念,帮助你快速掌握其使用方式。

一、安装与基础结构

React Router v5 需要安装 react-router-dom 包,并通过 BrowserRouterRouteSwitch 等组件实现路由功能。

npm install react-router-dom@5.x

1. 基础路由配置

import { BrowserRouter, Route, Switch } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/home" component={Home} />
        <Route path="/about" component={About} />
        <Route path="*" component={NotFound} /> {/* 404 页面 */}
      </Switch>
    </BrowserRouter>
  );
}

注意

<Switch> 是必须的,它会匹配第一个满足条件的 <Route>,避免多个路由同时渲染。

二、导航方式

1. 声明式导航( <Link>

使用 <Link> 组件实现页面跳转,类似于 v6 的 <Link>

<Link to="/home">首页</Link>
<Link to="/about">关于</Link>

2. 编程式导航( <Redirect> useHistory 钩子)

<Redirect>:用于手动跳转页面。

import { Redirect } from 'react-router-dom';

function LoginPage() {
  if (isLoggedIn) {
    return <Redirect to="/home" />;
  }
  return <div>登录页面</div>;
}
  • useHistory 钩子:用于动态跳转(React Hooks API)。
import { useHistory } from 'react-router-dom';

function Home() {
  const history = useHistory();

  const handleClick = () => {
    history.push('/about');
  };

  return <button onClick={handleClick}>跳转到 About</button>;
}

三、动态路由与参数

1. 动态路由参数

通过 :param 定义动态路由参数,使用 match.params 获取参数。

<Route path="/user/:id" component={User} />

获取参数:

import { withRouter } from 'react-router-dom';

function User({ match }) {
  const { id } = match.params;
  return <div>用户ID: {id}</div>;
}

2. 搜索参数

使用 location.search 获取 URL 中的查询参数:

import { withRouter } from 'react-router-dom';

function SearchPage({ location }) {
  const { q } = new URLSearchParams(location.search);
  return <div>搜索关键词: {q}</div>;
}

四、嵌套路由

1. 定义嵌套路由

使用 Routechildren 属性渲染子路由内容,搭配 Switch 实现嵌套。

<Route path="/layout">
  <Route path="home" component={Home} />
  <Route path="about" component={About} />
</Route>

2. 渲染子路由

使用 Outlet 组件(需要 react-router-dom@5.2.0 或以上版本):

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

function Layout() {
  return (
    <div>
      <Header />
      <Outlet /> {/* 渲染子路由内容 */}
    </div>
  );
}

五、路由守卫(导航守卫)

React Router v5 通过 componentrenderchildren 实现导航控制,没有现成的 beforeRoute 等钩子。

1. 权限校验(基于 component

<Route path="/private" component={PrivateRoute} />

PrivateRoute 组件:

function PrivateRoute({ component: Component, ...rest }) {
  const isAuthenticated = checkAuth(); // 自定义校验逻辑

  return (
    <Route
      {...rest}
      render={props =>
        isAuthenticated ? <Component {...props} /> : <Redirect to="/login" />
      }
    />
  );
}

2. 路由守卫(基于 component

<Route
  path="/user/:id"
  render={props => {
    if (isUserExist) {
      return <User {...props} />;
    }
    return <Redirect to="/404" />;
  }}
/>

六、路由模式(Hash/History)

1. Hash 模式

使用 BrowserRouterhashHistory,默认基于 window.location.hash 实现:

import { HashRouter } from 'react-router-dom';

function App() {
  return (
    <HashRouter>
      <Switch>
        <Route path="/home" component={Home} />
        <Route path="*" component={NotFound} />
      </Switch>
    </HashRouter>
  );
}

2. History 模式

需要服务器支持 history 模式,如 Nginx 配置:

location / {
  try_files $uri $uri/ /index.html;
}

v6

一、核心概念与结构

1. 路由配置

React Router v6 使用 declarative routing(声明式路由) ,通过函数组件和路由配置来定义路由规则。

2. <Routes> <Route> 组件

  • <Routes> 是嵌套的路由容器,必须包裹在 <Routes>
  • <Route> 用于定义路由路径和组件对应的映射关系。
import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="*" element={<NotFound />} /> {/* 404 页面 */}
    </Routes>
  );
}

⚠️ 注意

v6 中 <Route>component 属性已被弃用,改为 element,并需要传入一个 JSX 元素。

二、导航方式

1. 声明式导航( <Link>

使用 <Link> 组件进行页面跳转,避免直接修改 window.location

<Link to="/">首页</Link>
<Link to="/about">关于</Link>

2. 编程式导航( useNavigate

通过 useNavigate 钩子实现动态跳转,适用于按钮点击或条件判断的场景。

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

function Home() {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/about');
  };

  return (
    <button onClick={handleClick}>跳转到 About</button>
  );
}

三、路由参数与动态路由

1. 动态路由参数

使用 :param 语法定义动态路由参数,通过 useParams 获取参数。

<Route path="/user/:id" element={<User />} />

获取参数:

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

function User() {
  const { id } = useParams();
  return <div>用户ID: {id}</div>;
}

2. 搜索参数

通过 useSearchParams 获取 URL 中的查询参数。

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

function SearchPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  const query = searchParams.get('q');

  return (
    <div>搜索关键词: {query}</div>
  );
}

四、嵌套路由

1. 定义嵌套路由

使用 <Outlet> 组件渲染子路由内容,搭配 <Route> 定义动态嵌套路径。

<Route path="/" element={<Layout />}>
  <Route index element={<Home />} /> {/* 默认路由 */}
  <Route path="about" element={<About />} />
  <Route path="user/:id" element={<User />} />
</Route>

Layout 组件中渲染 <Outlet />

function Layout() {
  return (
    <div>
      <Header />
      <Outlet /> {/* 渲染子路由内容 */}
    </div>
  );
}

2. 动态嵌套路径

可以通过 useMatch 获取当前路由信息,实现动态嵌套路由逻辑。

import { useMatch } from 'react-router-dom';

function UserPage() {
  const match = useMatch('/user/:id');
  return <div>用户ID: {match.params.id}</div>;
}

五、路由守卫(导航守卫)

React Router v6 没有直接的 beforeRouteafterRoute 等守卫机制,但可以通过 useNavigate 配合条件判断实现基本的导航控制。

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

function ProtectedRoute({ children }) {
  const navigate = useNavigate();
  const isAuthenticated = checkAuth(); // 自定义认证逻辑

  if (!isAuthenticated) {
    navigate('/login');
  }

  return children;
}

六、路由模式(Hash/History)

1. Hash 模式

在开发时,为了避免配置服务器支持 history 模式,可以使用 createHashRouter,它基于 window.location.hash 实现。

import { createHashRouter } from 'react-router-dom';

const router = createHashRouter([
  { path: '/', element: <Home /> },
  { path: '/about', element: <About /> }
]);

export default router;

2. History 模式

若服务器已支持 history 模式,可以通过 createBrowserRouter 实现。

import { createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([
  { path: '/', element: <Home /> },
  { path: '/about', element: <About /> }
]);

export default router;

七、常见问题

1. 路由匹配错误

  • 确保路径分隔符使用 /,避免空格或拼写错误。
  • 确保 <Routes> 包裹所有路由,且 <Route> 不能直接放在 return 中。

2. 404 页面

  • 使用 path="*" 匹配所有未定义的路径。
<Route path="*" element={<NotFound />} />

3. 嵌套路由渲染问题

  • 确保父路由中包含 <Outlet /> 来渲染子路由内容。
  • 确保子路由路径不以 / 开头(否则会被视为绝对路径)。

v5 与 v6 的主要差异

特性React Router v5React Router v6
路由容器<BrowserRouter>/<HashRouter><BrowserRouter>/<HashRouter>
路由匹配<Switch> + <Route><Routes> + <Route>
component保留淘汰(改用 element
动态路由参数match.paramsparams 钩子
程序化导航history.push()/<Redirect>useNavigate() 钩子