React员工管理项目添加按钮点击报错:无法读取push属性
员工管理系统按钮跳转问题解决
问题描述
开发带基础CRUD功能的员工管理项目时,点击“添加员工”按钮无响应,抛出如下错误:
ListEmployeeComponent.jsx:21 Uncaught TypeError: Cannot read properties of undefined (reading 'push') at ListEmployeeComponent.addEmployee (ListEmployeeComponent.jsx:21:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1) at executeDispatch (react-dom.development.js:9041:1) at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1) at processDispatchQueue (react-dom.development.js:9086:1) at dispatchEventsForPlugins (react-dom.development.js:9097:1) at react-dom.development.js:9288:1
相关代码
ListEmployeeComponent.jsx
import React, { Component } from 'react'; import EmployeeService from '../services/EmployeeService'; class ListEmployeeComponent extends Component { constructor(props) { super(props) this.state = { employees : [] } this.addEmployee = this.addEmployee.bind(this); } componentDidMount(){ EmployeeService.getEmployees().then((res) => { this.setState({ employees : res.data }); }); } addEmployee(){ this.context.history.push("/add-employee"); } render() { return ( <div> <h2 className='text-center'>Employees List</h2> <div> <button className='btn btn-primary' onClick={this.addEmployee}> Add Employee </button> </div> <div className='row'> <table className='table table-striped table-bordered'> <thead> <tr> <th>Employee First Name</th> <th>Employee Last Name</th> <th>Employee Email Id</th> <th>Actions</th> </tr> </thead> <tbody> {this.state.employees.map(employee => <tr key={employee.id}> <td>{employee.firstName}</td> <td>{employee.lastName}</td> <td>{employee.emailId}</td> </tr> )} </tbody> </table> </div> </div> ); } } export default ListEmployeeComponent;
App.js
import './App.css'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom' import ListEmployeeComponent from './components/ListEmployeeComponent'; import CreateEmployeeComponent from './components/CreateEmployeeComponent'; import HeaderComponent from './components/HeaderComponent'; import FooterComponent from './components/FooterComponent'; function App() { return ( <div> <Router> <HeaderComponent /> <div className="container"> <Routes> <Route path='/' exact element={ <ListEmployeeComponent/> }></Route> <Route path='/employees' element={ <ListEmployeeComponent/> }></Route> <Route path='/add-employee' element= { <CreateEmployeeComponent/> }></Route> </Routes> </div> <FooterComponent /> </Router> </div> ); } export default App;
错误原因
你使用的是react-router-dom v6,该版本已移除类组件通过this.context.history获取路由对象的方式,也不再支持history.push直接跳转,因此调用this.context.history.push会因this.context.history未定义报错。
解决方法
方法一:改用函数组件 + useNavigate钩子
将类组件重构为函数组件,使用v6提供的useNavigate钩子实现跳转:
import React, { useEffect, useState } from 'react'; import EmployeeService from '../services/EmployeeService'; import { useNavigate } from 'react-router-dom'; function ListEmployeeComponent() { const [employees, setEmployees] = useState([]); const navigate = useNavigate(); useEffect(() => { EmployeeService.getEmployees().then((res) => { setEmployees(res.data); }); }, []); const addEmployee = () => { navigate("/add-employee"); } return ( <div> <h2 className='text-center'>员工列表</h2> <div> <button className='btn btn-primary' onClick={addEmployee}> 添加员工 </button> </div> <div className='row'> <table className='table table-striped table-bordered'> <thead> <tr> <th>员工名</th> <th>员工姓</th> <th>员工邮箱</th> <th>操作</th> </tr> </thead> <tbody> {employees.map(employee => <tr key={employee.id}> <td>{employee.firstName}</td> <td>{employee.lastName}</td> <td>{employee.emailId}</td> </tr> )} </tbody> </table> </div> </div> ); } export default ListEmployeeComponent;
方法二:封装withRouter高阶组件适配类组件
如果不想重构组件,可自行封装withRouter高阶组件,将路由方法注入类组件的props中:
- 创建
withRouter.js文件:
import { useNavigate, useLocation, useParams } from 'react-router-dom'; export const withRouter = (Component) => { function ComponentWithRouterProp(props) { let navigate = useNavigate(); let location = useLocation(); let params = useParams(); return <Component {...props} router={{ navigate, location, params }} />; } return ComponentWithRouterProp; };
- 修改
ListEmployeeComponent.jsx:
import React, { Component } from 'react'; import EmployeeService from '../services/EmployeeService'; import { withRouter } from './withRouter'; // 根据实际路径调整 class ListEmployeeComponent extends Component { constructor(props) { super(props) this.state = { employees : [] } this.addEmployee = this.addEmployee.bind(this); } componentDidMount(){ EmployeeService.getEmployees().then((res) => { this.setState({ employees : res.data }); }); } addEmployee(){ this.props.router.navigate("/add-employee"); } render() { return ( <div> <h2 className='text-center'>员工列表</h2> <div> <button className='btn btn-primary' onClick={this.addEmployee}> 添加员工 </button> </div> <div className='row'> <table className='table table-striped table-bordered'> <thead> <tr> <th>员工名</th> <th>员工姓</th> <th>员工邮箱</th> <th>操作</th> </tr> </thead> <tbody> {this.state.employees.map(employee => <tr key={employee.id}> <td>{employee.firstName}</td> <td>{employee.lastName}</td> <td>{employee.emailId}</td> </tr> )} </tbody> </table> </div> </div> ); } } export default withRouter(ListEmployeeComponent);
内容的提问来源于stack exchange,提问作者sandeep kande
相关产品推荐
相关产品推荐

