前言
matchRoutes
是 React Router v6
提供的一个核心工具函数,主要用于匹配路由配置与当前路径。它在服务端渲染 (SSR)、数据预加载 、权限校验等场景中非常实用。下面详细解析其用法、注意事项和案例分析:
1、基本用法
javascript
import { matchRoutes } from 'react-router-dom';
const routes = [
{ path: '/', element: <Home /> },
{ path: '/users', element: <Users /> },
{ path: '/users/:id', element: <UserDetail /> },
];
const location = { pathname: '/users/123' };
const matches = matchRoutes(routes, location);
返回值 matches
结构示例:
javascript
[
{
route: { path: '/users', element: <Users /> }, // 匹配的父路由
pathname: '/users', // 匹配的完整路径
pathnameBase: '/users', // 匹配的基础路径(不含子路由)
params: {} // 父路由参数
},
{
route: { path: '/users/:id', element: <UserDetail /> },
pathname: '/users/123',
pathnameBase: '/users/123',
params: { id: '123' } // 解析的动态参数
}
]
2、关键注意事项
2.1、返回数组结构
matchRoutes()
返回一个数组,包含所有匹配的嵌套路由对象(从根路由到叶子路由)。即使只有一个路由匹配,也会返回长度为1的数组。
2.2、路由配置必须完整
需传入完整的路由数组(包含所有嵌套的 children),否则深层路由无法匹配:
javascript
// ❌ 错误:缺少嵌套配置
const routes = [{ path: '/users', element: <Users /> }];
// ✅ 正确:包含子路由
const routes = [{
path: '/users',
element: <Users />,
children: [{ path: ':id', element: <UserDetail /> }]
}];
2.3、动态参数解析
动态参数(如 :id)会被自动解析并存入 match.params 中。
2.4、通配符路由 * 匹配
通配符路由只在没有其他路由匹配时生效:
javascript
const routes = [
{ path: '/users', element: <Users /> },
{ path: '/*', element: <NotFound /> }
];
matchRoutes(routes, { pathname: '/unknown' }); // 匹配 /* 路由
2.5、索引路由(Index Route)匹配
当路径精确匹配父路由时,会匹配 index: true
的子路由:
javascript
const routes = [{
path: '/dashboard',
element: <DashboardLayout>,
children: [
{ index: true, element: <DashboardHome /> }, // 匹配 /dashboard
{ path: 'settings', element: <Settings /> }
]
}];
2.6、大小写敏感问题
默认不区分大小写。如需区分,在路由配置中设置 caseSensitive: true:
javascript
{ path: '/CaseSensitive', caseSensitive: true, element: <Component /> }
3、常见应用场景
3.1、 服务端渲染(SSR
)数据预取
javascript
// 服务端代码
import { matchRoutes } from 'react-router-dom/server';
function handleRequest(req, res) {
const matches = matchRoutes(routes, req.url);
const promises = matches.map(match => {
// 假设路由组件有静态方法 loadData
return match.route.element?.type?.loadData?.(match);
});
Promise.all(promises).then(() => {
// 数据加载完成后渲染应用
const html = renderToString(<App />);
res.send(html);
});
}
3.2、 客户端权限校验
javascript
// 路由守卫组件
const AuthGuard = ({ children }) => {
const location = useLocation();
const matches = matchRoutes(routes, location);
const needAuth = matches?.some(match =>
match.route.requiresAuth
);
if (needAuth && !isLoggedIn) {
return <Redirect to="/login" />;
}
return children;
};
3.3、 提取动态参数(非组件环境)
javascript
// 工具函数中获取参数
function getUserIdFromPath(pathname) {
const matches = matchRoutes(
[{ path: '/users/:id' }],
pathname
);
return matches?.[0]?.params.id; // '123'
}
4、易错点与解决方案
返回 null 的问题 : 是路径未匹配任何路由, 需要检查路由配置或添加通配符路由 /*
子路由未匹配 的原因 :是父路由配置未包含 children, 需要确保路由配置包含完整的嵌套结构
参数未解析 的原因 : 是动态路由拼写错误(如 :ID vs :id), 需要检查路由的 path 定义一致性
索引路由不生效 的原因: 是父路由路径后有额外字符(如 /dashboard/), 需要确保路径精确匹配父路由
5、替代方案对比
useMatch Hook
:仅在组件内使用,返回当前路由的匹配信息。
useParams Hook
:组件内获取动态参数。
手动正则匹配:不推荐,维护成本高且易出错。
总结
matchRoutes
的核心价值在于在非组件环境中获得路由匹配信息。关键要点:
- 传入完整的路由配置(含
children
) - 返回值是数组,需遍历处理多层匹配
- 善用
pathnameBase
和params
解析路径信息 - 在 SSR、路由拦截、工具函数中优先使用它
- 正确使用此 API 能显著提升路由控制的灵活性与代码可维护性。