React Router v6配置编辑页带参路由获取params报错排查
问题根因
报错核心是两个点:React Router v6 版本API和旧版v5不兼容,加上代码里的笔误,和你路由配置的element写法没关系:
- React Router v6 已经废弃了旧版的
component、render路由配置属性,所有路由必须通过element传入React节点,所以你换这两个属性的时候会报缺少element的错误,Main.js里现有的路由配置写法是对的,不用改。 - v6 不再自动给类组件注入
match/history/location这几个路由props,所以你直接访问this.props.match拿到的是undefined,读params的时候自然会报错。 - EditVehicle组件里还有个低级笔误:给price字段赋值的时候写的是
res.date.price,正确应该是res.data.price,就算路由问题修了,这里也会报价格读取错误。
修复方案
两种方案选一种就行,第一种改造成本最低,不需要推翻现有类组件逻辑。
方案1:用高阶组件包装类组件(改造成本最低)
React Router v6可以通过钩子+包装组件的方式,手动把路由参数、导航方法注入到类组件props里,步骤如下:
- 修改EditVehicle.js的导入部分,引入v6的路由钩子:
import { Link, useParams, useNavigate } from "react-router-dom";
- 在EditVehicle类定义的后面、导出语句之前,加一个包装组件:
function RouterWrapper(props) { const params = useParams(); const navigate = useNavigate(); return <EditVehicle {...props} params={params} navigate={navigate} />; }
- 修改导出语句,导出包装后的组件:
export default RouterWrapper;
- 替换组件里的旧路由API调用:
- 所有
this.props.match.params.id替换为this.props.params.id - 提交成功后的跳转
this.props.history.push("/")替换为this.props.navigate("/")
- 所有
- 修复笔误:把
price: res.date.price改成price: res.data.price
改完之后直接运行就行,Main.js的路由配置不需要做任何调整。
方案2:改写为函数组件(符合React主流开发规范,长期维护更方便)
如果不想加包装层,可以直接把EditVehicle改成函数组件,直接调用v6的钩子获取参数和导航方法,示例代码:
import React, { useEffect, useState } from "react"; import axios from "axios"; import { Link, useParams, useNavigate } from "react-router-dom"; const EditVehicle = () => { const { id } = useParams(); const navigate = useNavigate(); const [formData, setFormData] = useState({ make: "", model: "", year: "", price: "", isSold: "" }); useEffect(() => { axios.get(`http://localhost:5000/vehicles/editVehicle/${id}`) .then(res => { setFormData({ make: res.data.make, model: res.data.model, year: res.data.year, price: res.data.price, isSold: res.data.isSold }) }) .catch(err => console.log(err)); }, [id]); const changeHandler = (e) => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; const submitHandler = (e) => { e.preventDefault(); axios.post(`http://localhost:5000/vehicles/editVehicle/${id}`, formData) .then(res => { console.log(res); navigate("/"); }) .catch(err => console.log(err)); }; return ( <div className="editVehicle"> <form className="editVehicle_form" onSubmit={submitHandler}> <Link to="/" className="back_btn">Back</Link> <h1>Update Vehicle Details</h1> <p>Please fill out all fields</p> <input name="make" placeholder="Make" type="text" value={formData.make} onChange={changeHandler} className="editVehicle_form_input" /> <br /> <input name="model" placeholder="Model" type="text" value={formData.model} onChange={changeHandler} className="editVehicle_form_input" /> <br /> <input name="year" placeholder="Year" type="text" value={formData.year} onChange={changeHandler} className="editVehicle_form_input" /> <br /> <input name="price" placeholder="Price" type="text" value={formData.price} onChange={changeHandler} className="editVehicle_form_input" /> <br /> <label className="addVehicle_form_radio_label"> Available <input name="isSold" type="radio" value={false} onChange={changeHandler} className="editVehicle_form_radio" /> </label> <label className="editVehicle_form_radio_label"> Sold <input name="isSold" type="radio" value={true} onChange={changeHandler} className="editVehicle_form_radio" /> </label> <br /> <input type="submit" value="Save" className="editVehicle_submit" /> </form> </div> ) } export default EditVehicle;
额外优化建议
你在VehicleList的删除逻辑里调用了window.location.reload()整页刷新,这步完全多余,删除请求返回成功后直接调用getVehicleList()更新本地状态就能刷新列表,整页刷新会导致页面闪屏、损失性能。
内容的提问来源于stack exchange,提问作者Tubby_Noah
相关产品推荐
相关产品推荐

