You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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中:

  1. 创建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;
};
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:25:23