使用axios.post提交民宿信息首次报重复ID错误的问题排查与修复
问题描述
开发民宿介绍社区看板时,使用axios.post结合表单提交新增民宿信息,页面渲染完成后首次提交控制台提示insert failed, duplicate id,但后续提交无报错且能正常写入json-server对应的JSON文件。相关代码如下:
const handleSubmit = e => { e.preventDefault() toggleModale() axios.get("http://localhost:3001/Home") //this is just for id test, not in real program .then(Response => { setData(Response.data.length) console.log("sucsess") }) .catch(Error => console.log(Error)) const Home = { home_spot: e.target.home_spot.value, tag: e.target.tag.value, home_image: e.target.home_image.value, home_name: e.target.home_name.value, home_site: e.target.home_site.value, home_price: e.target.home_price.value, reason: e.target.reason.value, home_open: e.target.home_open.checked, category: e.target.category.value } axios.post("http://localhost:3001/Home", { id: data.length + 1, home_spot: Home.home_spot, tag: Home.tag, home_image: Home.home_image, home_name: Home.home_name, home_site: Home.home_site, home_price: Home.home_price, reason: Home.reason, home_open: Home.home_open, category: Home.category, }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); } // localhost:3001/Home is json file with json-server
问题原因
- 异步执行顺序冲突:
axios.get是异步请求,执行时不会阻塞后续代码,导致axios.post在get请求的回调(更新data状态)之前就执行了。 - React状态更新的异步性:即使
get请求回调里调用了setData,data的更新也不是同步完成的,首次提交时data还是初始值(比如初始为空数组,length为0)。 - ID重复冲突:如果json-server初始JSON文件里已经存在
id=1的民宿数据,首次提交时生成的id=0+1=1就会和已有数据重复,触发报错。后续提交时,之前的get请求已经完成,data更新为正确的列表长度,生成的ID不会重复,所以可以正常提交。
修复方案
方案一:确保获取最新数据后再提交(手动生成ID)
把axios.post放到axios.get的回调函数里,保证拿到最新的列表长度后再生成ID:
const handleSubmit = e => { e.preventDefault() toggleModale() const Home = { home_spot: e.target.home_spot.value, tag: e.target.tag.value, home_image: e.target.home_image.value, home_name: e.target.home_name.value, home_site: e.target.home_site.value, home_price: e.target.home_price.value, reason: e.target.reason.value, home_open: e.target.home_open.checked, category: e.target.category.value } axios.get("http://localhost:3001/Home") .then(response => { const newId = response.data.length + 1 // 拿到最新长度后再发起post请求 return axios.post("http://localhost:3001/Home", { id: newId, ...Home }) }) .then(function (response) { console.log(response); // 可选:在这里重新获取列表更新本地状态 }) .catch(function (error) { console.log(error); }); }
方案二:让json-server自动生成ID(推荐)
json-server默认会为新增的资源自动生成递增的ID,不需要手动设置。直接去掉post数据里的id字段即可:
const handleSubmit = e => { e.preventDefault() toggleModale() const Home = { home_spot: e.target.home_spot.value, tag: e.target.tag.value, home_image: e.target.home_image.value, home_name: e.target.home_name.value, home_site: e.target.home_site.value, home_price: e.target.home_price.value, reason: e.target.reason.value, home_open: e.target.home_open.checked, category: e.target.category.value } // 去掉id字段,让json-server自动生成 axios.post("http://localhost:3001/Home", Home) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); }
内容的提问来源于stack exchange,提问作者대훈조
相关产品推荐
相关产品推荐

