前言
在单页应用里,路由跳转就像快递员把包裹送到另一个房间。包裹怎么装?地址怎么写?收件人怎么拆?每一步都决定包裹能否安全、准时、完整地送达。React Router 提供了三种最常用的"快递方式"------查询参数、路径参数和 state 隐式参数------它们各有优缺点、适用场景。
很多初学者容易混淆这三种方式:
- 把本该公开分享的筛选条件写进了 state,结果刷新页面就"丢件";
- 把只能临时使用的滚动位置写进了查询字符串,导致 URL 又丑又长;
- 把对象直接塞进路径参数,结果浏览器直接 404。
本文带你快速掌握三种传参方式的核心差异。
一、 查询参数
① 路由声明
无需占位符,直接写静态路径。
js
{ path: '/noteList', element: <NoteList /> }
② 路由跳转
声明式
js
import { Link } from 'react-router-dom';
<Link to={{ pathname: '/noteList', search: '?category=1&page=2' }}>
查看分类 1 第 2 页
</Link>
命令式
js
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate({ pathname: '/noteList', search: '?category=1&page=2' });
search
必须是 '?key=value' 的完整字符串,也可以自己拼。
③ 路由接收:useSearchParams()
js
import { useSearchParams } from 'react-router-dom';
function NoteList() {
const [searchParams] = useSearchParams();
const category = searchParams.get('category'); // "1"
const page = Number(searchParams.get('page')) || 1;
return <>分类:{category} 第 {page} 页</>;
}
URL 上有 ?key=value
,参数留在地址栏,刷新不丢 ,适合筛选、分页、排序。
二、路径参数
① 路由声明
在 path
中用冒号 :
占位。
js
{ path: '/noteList/:category', element: <NoteList /> }
② 路由跳转
js
<Link to="/noteList/123">分类 123</Link>
// 或
navigate('/noteList/123');
③ 路由接收: useParams()
js
import { useParams } from 'react-router-dom';
function NoteList() {
const { category } = useParams(); // "123"
return <>当前分类 ID:{category}</>;
}
刷新页面,数据不丢失。
三、state 隐式参数
① 路由声明
任何路由都能接。
js
{ path: '/noteList', element: <NoteList /> }
{ path: '/noteList/:category', element: <NoteList /> }
② 路由跳转
js
// 命令式
navigate('/noteList', { state: { category: 1, from: 'banner' } });
// 声明式
<Link to="/noteList" state={{ category: 1 }} />
③ 路由接收: useLocation()
js
import { useLocation } from 'react-router-dom';
function NoteList() {
const { state } = useLocation(); // { category: 1, from: 'banner' }
return <>来自:{state?.from}</>;
}
参数不会出现在 URL,刷新即消失 ,适合临时或一次性过渡数据(例如记住滚动位置)。
四、路由传参表
维度 | 查询参数(Query String) | 路径参数(Path Params) | 隐式参数(Location State) |
---|---|---|---|
URL 示例 | /noteList?category=1&page=2 |
/noteList/1 |
/noteList (无痕迹) |
路由声明 | { path: '/noteList', element: <NoteList /> } |
{ path: '/noteList/:category', element: <NoteList /> } |
{ path: '/noteList', element: <NoteList /> } |
跳转方式 | navigate('/noteList?category=1') |
navigate('/noteList/1') |
navigate('/noteList', { state: { category: 1 } }) |
接收 Hook | useSearchParams() 或 useLocation() + 手动解析 |
useParams() |
useLocation().state |
数据类型限制 | 仅字符串 | 仅字符串 | 任意类型(对象、数组等) |
刷新后保留 | ✅ | ✅ | ❌ |
能否分享/收藏 | ✅ | ✅ | ❌ |
URL 可读性 | 中(可能较长) | 高(简洁明了) | 最高(无参数痕迹) |
典型场景 | 列表筛选、分页、搜索关键词 | 详情页 ID、RESTful 资源定位 | 临时过渡数据(如返回滚动位置、表单结果) |