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:
- 创建
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; };
- 修改
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
相关产品推荐
相关产品推荐

