React类组件读取params报undefined 无法使用useParams求解决方案
错误原因
- 你当前使用的是react-router v6版本,该版本已经移除了类组件中原生支持的
this.props.match属性,因此你调用this.props.match.params.id时会触发Cannot read properties of undefined (reading 'params')报错。 useParams是react-router提供的Hook语法,仅支持在函数组件中调用,类组件内直接使用会报错。
可行解决方案
方案1:自定义withRouter高阶组件适配类组件(无需修改现有类组件核心逻辑)
react-router v6官方移除了原有的withRouter封装,你可以自行实现高阶组件注入路由参数:
- 在当前组件文件中添加自定义withRouter逻辑:
import { useParams, useNavigate, useLocation } from 'react-router-dom'; // 自定义高阶组件,为类组件注入路由相关属性 function withRouter(Component) { function ComponentWithRouterProp(props) { const location = useLocation(); const navigate = useNavigate(); const params = useParams(); return <Component {...props} router={{ location, navigate, params }} />; } return ComponentWithRouterProp; }
- 将原有获取id的逻辑替换:
把所有的const id = this.props.match.params.id替换为const id = this.props.router.params.id - 导出组件时用withRouter包裹:
export default withRouter(Feed2);
原有没用的import {useParams} from "react-router-dom"可以直接删除。
方案2:将类组件改写为函数组件(符合react-router v6的官方推荐写法)
改写后的完整代码如下,同时修复了你原代码中res.data.registration.color拼写错误的问题(少了s,应为res.data.registrations.color):
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { Dropdown } from "react-bootstrap"; import { useParams } from "react-router-dom"; const Feed2 = () => { // 直接用useParams获取路由id const { id } = useParams(); // 用useState管理表单状态 const [formData, setFormData] = useState({ vehicle: "", plateNo: "", owner: "", manufacturer: "", manufacturedYear: "", color: "" }); const takInput = (e) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const register = (e) => { e.preventDefault(); const { plateNo, owner, manufacturer, manufacturedYear, color, vehicle } = formData; const data = { plateNo, owner, manufacturer, manufacturedYear, color, vehicle }; console.log(data); axios.put(`http://localhost:8080/registrations/update/${id}`, data).then((res) => { if (res.data.success) { alert("Post Updated"); setFormData({ vehicle: "", plateNo: "", owner: "", manufacturer: "", manufacturedYear: "", color: "" }); } }); }; // 用useEffect替代componentDidMount生命周期 useEffect(() => { axios.get(`/registrations/${id}`).then((res) => { if (res.data.success) { setFormData({ plateNo: res.data.registrations.plateNo, owner: res.data.registrations.owner, manufacturer: res.data.registrations.manufacturer, manufacturedYear: res.data.registrations.manufacturedYear, color: res.data.registrations.color, vehicle: res.data.registrations.vehicle }); } }); }, [id]); return ( <div className="container"> <div className="register-box"> <div className="Top"> <div className="box"> <input placeholder="Enter the licence plate number " className="input2" name="plateNo" value={formData.plateNo} onChange={takInput} /> </div> </div> <div className="box"> <input placeholder="Enter the owners name " className="input2" name="owner" value={formData.owner} onChange={takInput} /> </div> <div className="box"> <input placeholder=" Manufactured Year " className="input2" name="manufacturedYear" value={formData.manufacturedYear} onChange={takInput} /> </div> <div className="box"> <input placeholder="Manufacturer" className="input2" name="manufacturer" value={formData.manufacturer} onChange={takInput} /> </div> <div className="box"> <input placeholder="Color of the vehicle " className="input2" name="color" value={formData.color} onChange={takInput} /> </div> <div className="box"> <input placeholder="Vehicle name " className="input2" name="vehicle" value={formData.vehicle} onChange={takInput} /> </div> <Dropdown className="drop"> <Dropdown.Toggle variant="success" id="dropdown-basic"> Select Vehicle Type </Dropdown.Toggle> <Dropdown.Menu> <Dropdown.Item href="#/action-1">Car</Dropdown.Item> <Dropdown.Item href="#/action-2">Van</Dropdown.Item> <Dropdown.Item href="#/action-3">Bus</Dropdown.Item> <Dropdown.Item href="#/action-3">Lorry</Dropdown.Item> <Dropdown.Item href="#/action-3">Three-weeler</Dropdown.Item> <Dropdown.Item href="#/action-3">Bike</Dropdown.Item> <Dropdown.Item href="#/action-3">Other</Dropdown.Item> </Dropdown.Menu> </Dropdown> <div className="regbuttonContainer"> <button className="Button" onClick={register}>Register Vehicle</button> </div> </div> </div> ); } export default Feed2;
内容的提问来源于stack exchange,提问作者Code With Banchi
相关产品推荐
相关产品推荐

