React路由this.props.history/navigate undefined跳转报错排查
React Router DOM v6 类组件路由跳转undefined问题解决方案
问题根因
react-router-domv6版本相比v5做了破坏性更新:- 移除了内置的
withRouter高阶组件 - 不再向路由渲染的组件默认注入
history/match/locationprops - 路由跳转API替换为仅支持函数组件调用的
useNavigate钩子
- 移除了内置的
- 自行实现的withRouter如果存在属性透传不全、API挂载位置错误的问题,就会出现修改后依然无法跳转的情况。
分步修复方案
1. 实现适配v6的withRouter高阶组件
新建工具文件src/utils/withRouter.js,写入以下代码,核心作用是把函数组件才能调用的路由钩子转为类组件可访问的props:
import { useNavigate, useLocation, useParams } from 'react-router-dom'; export const withRouter = (WrappedComponent) => { const RouterWrapper = (props) => { const navigate = useNavigate(); const location = useLocation(); const params = useParams(); return ( <WrappedComponent {...props} router={{ navigate, location, params }} /> ); }; return RouterWrapper; };
必须透传原组件接收的所有上层props,否则会出现组件传值丢失的问题。
2. 修改Main类组件的跳转逻辑
把类组件中所有调用this.props.history.push的代码,全部替换为调用this.props.router.navigate,对应GitHub搜索功能的示例代码如下:
// 原错误写法 // handleSearch = () => { // const { username, jumpToProfile } = this.state; // if (jumpToProfile) { // this.props.history.push(`/user/${username}`); // } else { // this.props.history.push(`/search?q=${username}`); // } // } // 修改后正确写法 handleSearch = () => { const { username, jumpToProfile } = this.state; if (jumpToProfile) { this.props.router.navigate(`/user/${username}`); } else { this.props.router.navigate(`/search?q=${username}`); } }
3. 调整组件导出和路由配置
- 在Main组件文件末尾,使用withRouter包裹组件后再导出:
export default withRouter(Main);
- 检查App.js路由配置,确保所有跳转目标路径都已正确注册在
<Routes>标签内,示例配置:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Main from './pages/Main'; import UserProfile from './pages/UserProfile'; import SearchResult from './pages/SearchResult'; function App() { return ( <Router> <Routes> <Route path="/" element={<Main />} /> <Route path="/user/:username" element={<UserProfile />} /> <Route path="/search" element={<SearchResult />} /> </Routes> </Router> ); } export default App;
常见失效场景排查
- 确认项目安装的
react-router-dom版本为6.x,不要混用v5、v6的API - 不要在
<Route>的element属性外层单独套withRouter,必须保证传入element的组件本身已经被withRouter包裹 - 如果调用跳转后地址栏变化但页面未渲染,检查目标路由的
<Route>标签是否写在<Routes>闭合标签内部,v6不支持Routes外的路由注册
内容的提问来源于stack exchange,提问作者genebent
相关产品推荐
相关产品推荐

