React Router 实战指南:从基础配置到参数传递
路由模式选型
react-router-dom 提供两种路由容器,需根据部署环境选择:
| 特性 | HashRouter | BrowserRouter |
|---|---|---|
| 实现原理 | location.hash 变化 | history.pushState API |
| URL 形态 | /#/user/profile | /user/profile |
| 服务器配置 | 无需处理 | 需配置 fallback |
| 本地文件访问 | 正常渲染 | 刷新 404 |
构建静态站点或需要直接打开 HTML 文件时,优先选用 HashRouter。
import { HashRouter } from 'react-router-dom'
import { createRoot } from 'react-dom/client'
import Root from './Root'
const container = document.getElementById('app')
createRoot(container).render(
<HashRouter>
<Root />
</HashRouter>
)定义路由映射
Switch 组件确保仅渲染首个匹配项,避免多路由同时激活:
import { Switch, Route, Redirect } from 'react-router-dom'
import Dashboard from './pages/Dashboard'
import Settings from './pages/Settings'
import NotFound from './pages/NotFound'
function Routes() {
return (
<Switch>
<Route exact path="/dashboard" component={Dashboard} />
<Route path="/settings" component={Settings} />
<Redirect from="/" to="/dashboard" exact />
<Route component={NotFound} />
</Switch>
)
}声明式导航
NavLink 支持 active 状态样式,适合导航菜单:
import { NavLink } from 'react-router-dom'
function Sidebar() {
const navClass = ({ isActive }) =>
isActive ? 'nav-item active' : 'nav-item'
return (
<nav>
<NavLink to="/dashboard" className={navClass}>
控制台
</NavLink>
<NavLink to="/settings/security" className={navClass}>
安全设置
</NavLink>
</nav>
)
}四种参数传递方案
方案一:动态路径参数
适用于标识资源的唯一 ID,参数可见且持久:
// 路由声明
<Route path="/article/:postId/:slug" component={Article} />
// 链接跳转
<Link to={`/article/${item.id}/${item.slug}`}>{item.title}</Link>
// 组件内读取
const Article = ({ match }) => {
const { postId, slug } = match.params
return <div>文章 {postId}</div>
}
// 编程式导航
history.push(`/article/${id}/${slug}`)方案二:URL 查询字符串
适合筛选条件、分页等场景:
// 路由无需特殊声明
<Route path="/search" component={SearchResult} />
// 构造查询参数
const query = new URLSearchParams()
query.append('keyword', keyword)
query.append('page', page)
<Link to={`/search?${query.toString()}`}>搜索</Link>
// 组件解析
import { useLocation } from 'react-router-dom'
const SearchResult = () => {
const location = useLocation()
const params = new URLSearchParams(location.search)
const keyword = params.get('keyword')
const page = params.get('page')
}方案三:隐式状态传递
数据不暴露于 URL,BrowserRouter 下刷新保留:
// 声明式
<Link
to={{
pathname: '/checkout',
state: { fromCart: true, items: cartItems }
}}
>
去结算
</Link>
// 编程式
history.replace('/checkout', { fromCart: true, items })
// 组件接收
const Checkout = ({ location }) => {
const { fromCart, items } = location.state || {}
}方案四:内存状态(已废弃)
早期版本的 query 对象传参,现已被 state 取代,不建议在新项目中使用。
非路由组件接入导航能力
withRouter 高阶组件为普通组件注入路由上下文:
import { withRouter } from 'react-router-dom'
function Toolbar({ history, location, match }) {
const handleBack = () => history.goBack()
const handleForward = () => history.goForward()
const jumpTo = (steps) => history.go(steps)
return (
<div className="toolbar">
<button onClick={handleBack}>← 后退</button>
<button onClick={handleForward}>前进 →</button>
<button onClick={() => jumpTo(-2)}>返回两步</button>
</div>
)
}
export default withRouter(Toolbar)选型建议
- 动态路径:资源定位明确,SEO 友好
- 查询参数:筛选、排序等临时状态
- state 传值:敏感数据或复杂对象传递