react-router-v7-params

7 min read
Table of Contents

1. 路径参数(Path Params)

1.1 定义方式

在路由配置中使用 :参数名 的形式定义路径参数:

tsapp/routes.ts
{
path: 'test/:id',
file: './pages/Test/index.tsx',
}

1.2 传递参数

方式一:直接拼接 URL

typescript
// 使用 navigate
navigate('/index/test/123')
// 使用 Link
<Link to="/index/test/123">跳转</Link>

方式二:使用对象形式(推荐)

typescript
// 使用 navigate
navigate({
pathname: '/index/test',
params: { id: '123' }
})
// 使用 Link
<Link to={{ pathname: '/index/test', params: { id: '123' } }}>跳转</Link>

1.3 接收参数

使用 useParams() Hook 获取路径参数:

typescript
import { useParams } from 'react-router'
export default function Test() {
const { id } = useParams()
return <div>Test Params: {id}</div>
}

1.4 特点

  • 参数直接显示在 URL 路径中
  • 刷新页面参数不会丢失
  • 可以分享带参数的 URL
  • 适合必填参数
  • ⚠️ URL 路径会变长
  • ⚠️ 参数类型只能是字符串

1.5 项目示例

路由配置 (app/routes.ts):

typescript
{
path: 'test/:id',
file: './pages/Test/index.tsx',
}

导航 (app/layout/Menu/index.tsx):

typescript
navigate('/index/test/123')

接收 (app/pages/Test/index.tsx):

typescript
const { id } = useParams()

2. 查询参数(Search Params / Query Params)

2.1 定义方式

查询参数不需要在路由配置中定义,直接在 URL 后添加 ?key=value 即可。

tsapp/routes.ts
{
path: 'search',
file: './pages/Search/index.tsx',
}

2.2 传递参数

2.2.1:直接拼接 URL

typescript
// 使用 navigate
navigate('/index/search?id=123&name=test')
// 使用 Link
<Link to="/index/search?id=123&name=test">跳转</Link>

2.2.2:使用对象形式(推荐)

typescript
// 使用 navigate
navigate({
pathname: '/index/search',
search: '?id=123&name=test'
})
// 或使用 URLSearchParams
const params = new URLSearchParams({ id: '123', name: 'test' })
navigate({
pathname: '/index/search',
search: params.toString()
})

2.3 接收参数

使用 useSearchParams() Hook 获取查询参数:

typescript
import { useSearchParams } from 'react-router'
export default function Search() {
const [searchParams, setSearchParams] = useSearchParams()
// 获取单个参数
const id = searchParams.get('id')
const name = searchParams.get('name')
// 获取所有参数
const allParams = Object.fromEntries(searchParams)
// 更新参数
const updateParams = () => {
setSearchParams({ id: '456', name: 'new' })
}
return (
<div>
<div>ID: {id}</div>
<div>Name: {name}</div>
<button onClick={updateParams}>更新参数</button>
</div>
)
}

2.4 特点

  • 参数不改变 URL 路径结构
  • 可以传递多个参数
  • 刷新页面参数不会丢失
  • 可以分享带参数的 URL
  • 适合可选参数或筛选条件
  • ⚠️ URL 会变长
  • ⚠️ 参数类型只能是字符串

2.5 项目示例

路由配置 (app/routes.ts):

typescript
{
path: 'search',
file: './pages/Search/index.tsx',
}

导航 (app/layout/Menu/index.tsx):

typescript
navigate('/index/search?id=123')

接收 (app/pages/Search/index.tsx):

typescript
const [searchParams] = useSearchParams()
const id = searchParams.get('id')

3. 状态传参(State)

3.1 定义方式

状态参数不需要在路由配置中定义,通过 navigateLinkstate 属性传递。

3.2 传递参数

使用 navigate

typescript
import { useNavigate } from 'react-router'
function Component() {
const navigate = useNavigate()
const handleNavigate = () => {
navigate('/index/about', {
state: {
id: 123,
name: 'test',
data: { foo: 'bar' }
}
})
}
return <button onClick={handleNavigate}>跳转</button>
}
typescript
import { Link } from 'react-router'
function Component() {
return (
<Link
to="/index/about"
state={{ id: 123, name: 'test' }}
>
跳转
</Link>
)
}

3.3 接收参数

使用 useLocation() Hook 获取状态参数:

typescript
import { useLocation } from 'react-router'
export default function About() {
const location = useLocation()
const state = location.state as { id: number; name: string } | null
return (
<div>
{state && (
<>
<div>ID: {state.id}</div>
<div>Name: {state.name}</div>
</>
)}
</div>
)
}

3.4 特点

  • 可以传递复杂对象(不仅仅是字符串)
  • 参数不会显示在 URL 中(更安全)
  • 适合传递敏感数据或临时数据
  • 刷新页面参数会丢失
  • 不能通过 URL 分享参数
  • 浏览器前进/后退可能丢失状态

3.5 使用场景

  • 传递表单数据到详情页
  • 传递临时状态信息
  • 传递不需要在 URL 中显示的数据

4. 对比总结

特性路径参数查询参数状态传参
URL 显示 显示在路径中 显示在查询字符串 不显示
刷新保留 保留 保留 丢失
可分享 可以 可以 不可以
参数类型字符串字符串任意类型
必填性适合必填适合可选任意
URL 长度中等较长不变
安全性中等中等较高
使用场景资源 ID、必填参数筛选条件、可选参数临时数据、复杂对象

5. 最佳实践

5.1 选择建议

  • 路径参数:用于标识资源的唯一 ID(如用户 ID、文章 ID)
  • 查询参数:用于筛选、排序、分页等可选参数
  • 状态传参:用于临时数据、复杂对象、敏感信息

5.2 组合使用

可以同时使用多种传参方式:

typescript
// 路径参数 + 查询参数
navigate('/index/user/123?tab=profile&sort=asc')
// 路径参数 + 状态传参
navigate('/index/user/123', {
state: { from: 'dashboard' }
})
// 查询参数 + 状态传参
navigate('/index/search?q=keyword', {
state: { filters: { category: 'tech' } }
})

5.3 类型安全

建议为参数定义类型:

typescript
// 路径参数类型
type PathParams = {
id: string
}
// 查询参数类型
type SearchParams = {
id?: string
name?: string
page?: string
}
// 状态参数类型
type LocationState = {
id: number
name: string
data?: Record<string, unknown>
}
// 使用
const { id } = useParams<PathParams>()
const [searchParams] = useSearchParams()
const location = useLocation()
const state = location.state as LocationState | null

6. 相关 API 参考

6.1 Hooks

  • useParams() - 获取路径参数
  • useSearchParams() - 获取和设置查询参数
  • useLocation() - 获取 location 对象(包含 state)
  • useNavigate() - 编程式导航

6.2 组件

  • <Link> - 声明式导航组件
  • <NavLink> - 带激活状态的导航组件

6.3 方法

  • navigate(path, options?) - 编程式导航
    • path: 路径字符串或对象
    • options.state: 状态数据
    • options.replace: 是否替换历史记录

参考资料

后记

My avatar

感谢你读到这里。

这座小站更像一份持续维护的“终端笔记”:记录我解决问题的过程,也记录走过的弯路。

如果这篇内容对你有一点点帮助:

  • 点个赞 / 收藏一下,方便你下次回来继续翻
  • 欢迎在评论区补充你的做法(或者指出我的疏漏)
  • 想持续收到更新:可以订阅 RSS(在页面底部)

我们下篇见。


More Posts

评论

评论 (0)

请先登录后再发表评论

加载中...