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

React 18类组件添加页面跳转按钮报错,求解决方案

React 18类组件添加跳转按钮报错的解决方法

问题根源

你遇到的报错是因为**useNavigate是React Router的Hook,只能在函数组件或自定义Hook内部调用**,不能直接在类组件或普通函数中使用,而你写的AddEmployee是普通函数,直接调用useNavigate违反了Hook的使用规则。

错误代码分析

原跳转函数的问题在于直接在普通函数中调用Hook:

import { useNavigate } from 'react-router';

export function AddEmployee(a, b) {
    let navigate = useNavigate(); // 错误:Hook不能在普通函数中调用
    return (
      navigate('http://localhost:3000/add-employee')
    );
}

解决方案

方法1:自定义withRouter高阶组件包裹类组件

React Router v6移除了官方的withRouter,需要自己实现它来给类组件传递navigate:

  1. 创建withRouter.js文件:
import { useNavigate, useLocation, useParams } from 'react-router-dom';
import React from 'react';

export const withRouter = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();
    const location = useLocation();
    const params = useParams();
    return <Component {...props} navigate={navigate} location={location} params={params} />;
  };
  return Wrapper;
};
  1. 修改ListEmployeeComponent组件:
import React from 'react';
import EmployeeService from '../Services/EmployeeService';
import { withRouter } from './withRouter';

class ListEmployeeComponent extends React.Component {
    constructor(props) {
        super(props)
        this.state={
            employees: []
        }
        this.handleAddEmployee = this.handleAddEmployee.bind(this);
    }

    componentDidMount() {
        EmployeeService.getEmployees().then((res) => {
            this.setState({employees:res.data});
        });
    }

    handleAddEmployee() {
        // 使用props传递的navigate跳转,用相对路径更灵活
        this.props.navigate('/add-employee');
    }

    render() {
        return (
            <div>
                <h2 className='text-center'>Employee List</h2>
                <div className='row'>
                    <button className='btn btn-primary' onClick={this.handleAddEmployee}>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 Name</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.email}</td>
                                    </tr>
                                )
                            }
                        </tbody>
                    </table>
                </div>
            </div>
        );
    }
}

// 用withRouter包裹后导出组件
export default withRouter(ListEmployeeComponent);

方法2:将类组件转为函数组件

如果项目允许,直接改成函数组件就能正常使用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 handleAddEmployee = () => {
        navigate('/add-employee');
    };

    return (
        <div>
            <h2 className='text-center'>Employee List</h2>
            <div className='row'>
                <button className='btn btn-primary' onClick={handleAddEmployee}>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 Name</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {
                            employees.map(
                                employee =>
                                <tr key={employee.id}>
                                    <td>{employee.firstName}</td>
                                    <td>{employee.lastName}</td>
                                    <td>{employee.email}</td>
                                </tr>
                            )
                        }
                    </tbody>
                </table>
            </div>
        </div>
    );
}

export default ListEmployeeComponent;

方法3:从父函数组件传递navigate

如果ListEmployeeComponent是被某个函数组件渲染的,可以直接把navigate作为props传进来:

// 父函数组件示例
import { useNavigate } from 'react-router-dom';
import ListEmployeeComponent from './ListEmployeeComponent';

function ParentPage() {
  const navigate = useNavigate();
  return <ListEmployeeComponent navigate={navigate} />;
}

// ListEmployeeComponent类组件中使用
handleAddEmployee() {
  this.props.navigate('/add-employee');
}

注意事项

  • 跳转路径优先用相对路径(如/add-employee),不要写完整URL,适配不同部署环境。
  • Hook必须在函数组件或自定义Hook的顶层调用,不能在类组件、普通函数、循环/条件语句中使用。

内容的提问来源于stack exchange,提问作者Aleksandr Valuyskov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:15:39