React项目怎么配置路由实现页面跳转

文章导读
React 里的“页面跳转”通常由两件事组成:一张把 URL 映射到组件的路由表,和触发跳转的动作(点击链接,或者在代码里调用导航函数)。多数配置失败不是不会写,而是版本写法和部署方式没对上。所以先确认版本和路由模式,再动手改,比直接复制一份配置更稳。
📋 目录
  1. 一 先确认当前场景和目标
  2. 二 按这个顺序处理
  3. 三 改完后怎么验证
  4. 四 容易忽略的边界
A A

React 里的“页面跳转”通常由两件事组成:一张把 URL 映射到组件的路由表,和触发跳转的动作(点击链接,或者在代码里调用导航函数)。多数配置失败不是不会写,而是版本写法和部署方式没对上。所以先确认版本和路由模式,再动手改,比直接复制一份配置更稳。

适用场景:单页应用需要在多个视图之间切换、带路由参数、或登录成功后跳转。处理动作:先确认 react-router-dom 的大版本和路由模式,再在入口包一层 Router、用 Routes/Route 定义路由表、在页面里用 Link 或 useNavigate 跳转。验证看地址栏是否变化、刷新当前路径是否 404、参数页能否直接打开。边界:BrowserRouter 要求服务端把未知路径回落到 index.html,部署在子目录要配 basename,纯静态托管可退回 HashRouter。

先确认当前场景和目标

动手前先确认四件事:一是项目是否已经装了路由库,装的是哪个大版本;二是路由模式用 BrowserRouter 还是 HashRouter;三是跳转方式是声明式链接为主,还是表单提交后的编程式跳转;四是页面结构是否需要嵌套布局和路由参数。

版本最关键。v5 的写法是 Switch 加 component 或 render,v6 换成了 Routes 加 element,参数也从组件 props 读取改成 useParams。把 v5 示例贴进 v6 项目,最常见的现象是页面空白、控制台提示某个导出不存在。可以先看一下依赖:

# 查看当前安装的路由库版本
npm ls react-router-dom

# 如果还没装(以 v6 写法为例)
npm install react-router-dom

再看部署环境。如果页面由 Nginx、Node 服务或静态托管提供,并且需要用户能直接访问 /users/1 这类地址,就必须让服务端把未命中的路径回落到 index.html,否则刷新会拿到 404。没有条件改服务端配置时,HashRouter 是更省事的退路,代价是地址栏带 #。

React项目怎么配置路由实现页面跳转

按这个顺序处理

建议的顺序是:入口挂 Router → 定义路由表 → 页面内跳转 → 补 404 → 需要时再拆包。下面是一个可替换的通用骨架,v6 写法,路径和组件名按自己的目录改。

第一步,在最外层包一个 Router,整个应用只能有一层:

// src/main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'

ReactDOM.createRoot(document.getElementById('root')).render(
  <BrowserRouter basename="/">
    <App />
  </BrowserRouter>
)

basename 要和实际部署的子路径一致,部署在根目录就写 "/"。

React项目怎么配置路由实现页面跳转

第二步,用 Routes 和 Route 声明路由表。需要公共头部、侧边栏时,用父路由加 Outlet 占位,子路由写在父路由内部,子路径不要以 / 开头:

// src/App.jsx
import { Routes, Route, Link, Outlet } from 'react-router-dom'
import Home from './pages/Home'
import UserList from './pages/UserList'
import UserDetail from './pages/UserDetail'
import NotFound from './pages/NotFound'

function Layout() {
  return (
    <div>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/users">用户列表</Link>
      </nav>
      <Outlet />
    </div>
  )
}

export default function App() {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="users" element={<UserList />} />
        <Route path="users/:id" element={<UserDetail />} />
        <Route path="*" element={<NotFound />} />
      </Route>
    </Routes>
  )
}

第三步,页面内跳转。普通导航用 Link,它会渲染成可被搜索引擎和键盘操作的 <a>;只有在提交表单、条件判断之后才需要 useNavigate:

React项目怎么配置路由实现页面跳转
// src/pages/UserList.jsx
import { useNavigate, useSearchParams } from 'react-router-dom'

export default function UserList() {
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()

  const goDetail = (id) => {
    navigate(/users/${id})                       // 新增一条历史记录
    // navigate(/users/${id}, { replace: true }) // 替换当前记录,返回时不回退到列表
  }

  return (
    <div>
      <button onClick={() => goDetail(1)}>查看用户 1</button>
      <button onClick={() => setSearchParams({ page: '2' })}>第二页</button>
    </div>
  )
}

详情页用 useParams 取 id,取不到或数据不存在时给出提示,不要直接渲染空对象字段。数据量大或页面较重时,再把 element 换成 React.lazy 加 Suspense 包裹的组件,先保证跳转逻辑跑通,再考虑拆包。

改完后怎么验证

按下面几项逐条走一遍,比只看一次跳转成功更可靠:

  1. 点导航链接,地址栏应变化且页面内容切换,浏览器前进、后退按钮能正常来回。
  2. 在详情页地址上按 F5 刷新,页面应正常渲染;如果返回 404 或空白,说明服务端未配置路径回落,或 basename 与实际部署路径不一致。
  3. 手动在地址栏输入 /users/1、/users/abc 和一个不存在的路径,确认参数页能直达、非法参数有提示、未命中走 404 组件。
  4. 提交表单后调用 navigate,确认成功跳走,并且按浏览器返回键不会回到已提交的页面(需要的话改用 replace: true)。
  5. 看控制台:不应出现“不能在 Router 外使用 useNavigate”之类的报错,也不应出现路由组件未更新的警告。
  6. 使用了懒加载时,在网络面板里应看到对应页面的分块文件在首次进入时被请求。

预期信号是:地址栏、页面内容、浏览器历史三者一致,刷新任何一条已定义路由都不会落到白屏。

容易忽略的边界

  • 版本混用:v5 的 Switch、useHistory 在 v6 中已不可用,对应 Routes、useNavigate;如果项目里同时存在两套写法,先统一版本再改页面,不要边改边升级。
  • 嵌套 Router:在组件内部又包了一层 BrowserRouter 会导致跳转异常或路由表失效,整个应用只保留最外层一层。
  • 子路径与相对跳转:部署在 /admin 这类子目录时,Router 的 basename、静态资源的 publicPath、后端回落规则三处要一致,漏一处就会出现刷新后资源 404。
  • 权限拦截:登录态判断不要写在渲染期直接改 location,建议用包装组件,未登录时返回 <Navigate to="/login" replace />,避免首页闪一下再跳走。
  • navigate(-1) 的局限:用户从外部链接直接进入详情页时,历史里没有上一页,回退可能离开站点,这类页面建议提供明确的“返回列表”链接。
  • HashRouter 的适用面:它能绕开服务端回落配置,但地址带 #,部分统计和分享场景需要额外处理。若后续改造成本可控,仍建议优先把服务端回落配好再用 BrowserRouter。
  • 不适用条件:服务端渲染、微前端子应用、或已有其他路由框架的项目,不建议直接套用上面这份骨架,需要先确认路由归属和挂载基路径。