为什么点击触发history.push后会同时渲染两个React路由组件?
问题原因
- 路由匹配规则冲突:动态参数路由
/trains/:idTrain会将路径段alerts-list识别为合法的idTrain参数值,因此/trains/alerts-list会同时命中两个路由规则。 - 未使用独占匹配逻辑:React Router 默认是包容性匹配,所有命中规则的路由都会被渲染。如果你使用的是v5版本没有用
<Switch>包裹子路由、v6版本没有用<Routes>包裹子路由,就会出现多组件同时渲染的问题。 - 父路由配置冗余:你外层的
ProtectedRoute已经配置了包含两个目标路径的path数组,匹配成功后内部的两个子路由都会参与匹配,进一步导致多组件渲染。
修复方案
- 添加独占匹配包裹层
根据你使用的React Router版本,用对应组件包裹两个子路由,同时简化父路由配置:
// react-router v5 版本 import { Switch } from 'react-router-dom' <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} // 父路由直接匹配所有/trains开头的路径即可,不需要罗列所有子路径 path="/trains/*" > <Switch> <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} path={Routes.TrainsAlertsList.path} Component={TrainsAlertsListScreen} exact /> <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} path={Routes.TrainDetails.path} Component={TrainDetailsScreen} exact /> </Switch> </ProtectedRoute>
// react-router v6 版本 import { Routes } from 'react-router-dom' <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} path="/trains/*" > <Routes> <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} path={Routes.TrainsAlertsList.path} Component={TrainsAlertsListScreen} /> <ProtectedRoute requiredRoles={[ROLES.vehicleOperator, ROLES.vehicleAnalyst]} isAuth={isLogin} path={Routes.TrainDetails.path} Component={TrainDetailsScreen} /> </Routes> </ProtectedRoute>
- 调整路由排序
固定把静态路由放在动态参数路由前面,保证访问静态路径时优先命中静态路由,不会走到动态路由逻辑。 - 添加动态参数校验(可选)
如果你的idTrain是数字类型,可以给路由参数增加正则限制,从根源避免路径冲突:
TrainDetails: { path: '/trains/:idTrain(\\d+)', // 仅匹配数字类型的id参数 name: 'Train details', viewName: 'TRAIN_DETAILS', },
内容的提问来源于stack exchange,提问作者marcinb1986
相关产品推荐
相关产品推荐

