React.js中如何实现编程式导航?——解决点击登录按钮时出现TypeError: Cannot read property 'push' of undefined错误
嘿,我来帮你搞定这个问题!你遇到的TypeError: Cannot read property 'push' of undefined是因为你的组件没有被react-router-dom的路由上下文包裹,导致useHistory钩子无法获取到有效的history对象。下面我一步步给你讲清楚怎么实现编程式导航,以及解决这个错误的方法。
一、React.js编程式导航的核心方式
对于函数组件来说,最常用的编程式导航实现就是借助react-router-dom提供的钩子:
useHistory(适用于React Router v5及更早版本)useNavigate(适用于React Router v6版本,替代了useHistory)
它们的作用都是让你在代码逻辑里主动控制路由跳转,而不是依赖<Link>组件的点击跳转。
二、错误原因分析
你的代码里虽然调用了useHistory(),但如果你的App组件没有被BrowserRouter(或者HashRouter,根据你的路由模式选择)组件包裹的话,路由上下文就不存在,useHistory会返回undefined,自然就调用不了push方法了。
另外还要提个小细节:React中元素的类名属性是className,而不是原生HTML的class,这个也需要修正哦。
三、完整解决步骤与代码
步骤1:用路由上下文包裹根组件
首先找到你的项目入口文件(一般是index.js),用BrowserRouter把App组件包裹起来,这样整个应用都能访问到路由上下文了:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <BrowserRouter> <App /> </BrowserRouter> );
步骤2:修正App.js中的代码
下面是修正后的App组件代码,同时修复了class→className的问题:
import { useHistory } from 'react-router-dom'; function App() { const history = useHistory(); const handleClick = () => { // 跳转到dashboard页面 history.push("/dashboard"); } return ( <button type="submit" className="btn btn-danger mt-2" onClick={handleClick}> Login </button> ) } export default App;
四、如果你用的是React Router v6版本
如果你的项目安装的是React Router v6,useHistory已经被废弃了,需要改用useNavigate钩子,用法如下:
import { useNavigate } from 'react-router-dom'; function App() { const navigate = useNavigate(); const handleClick = () => { // 跳转到dashboard页面 navigate("/dashboard"); } return ( <button type="submit" className="btn btn-danger mt-2" onClick={handleClick}> Login </button> ) }
同样,v6版本也必须确保根组件被BrowserRouter包裹才能正常使用useNavigate。
内容的提问来源于stack exchange,提问作者Boidurja Talukdar

