MERN栈如何正确发送PUT请求更新数据及路由命名疑问
路由单复数说明
Express本身没有强制要求路由用单数还是复数,这只是RESTful API的通用命名约定,完全可以根据自己的需求自定义路由:
- 一般操作资源集合(查询全量列表、新增资源)用复数命名,比如
GET /animals查询所有动物、POST /animals/new新增动物 - 操作单个资源(修改、删除指定id的资源)用单数+id命名,比如
PUT /animal/update/:id更新单个动物、DELETE /animal/delete/:id删除单个动物
你看到的教程里/users和/user/new的区别只是教程的写法,不是Express的固有特性,自己项目里只要保持命名统一即可。
PUT请求实现修复
服务端代码问题修复
你现有server.js里的PUT路由存在两个错误:findOne需要传入查询条件对象,不能直接传id;且写死了更新值,没有读取请求体的参数,修改为:
app.put('/animal/update/:id', async (req, res) => { try { // 正确查询指定id的动物数据 const targetAnimal = await Animal.findById(req.params.id); if (!targetAnimal) return res.status(404).json({msg: '对应动物不存在'}); // 从请求体读取要更新的字段,没有传的字段保留原值 targetAnimal.phoneNumber = req.body.phoneNumber || targetAnimal.phoneNumber; targetAnimal.name = req.body.name || targetAnimal.name; targetAnimal.textHistory = req.body.textHistory || targetAnimal.textHistory; await targetAnimal.save(); res.json(targetAnimal); } catch (err) { res.status(500).json({error: err.message}); } })
前端代码问题修复
你现有App.js里的changePhone方法没有指定PUT请求方式,调用路径也和你写的服务端路由不匹配,修改为:
const changePhone = async id => { const updatedAnimal = await fetch(api_base + '/animal/update/' + id, { method: "PUT", headers: {"Content-Type": "application/json" }, // 把要更新的字段放到请求体 body: JSON.stringify({ phoneNumber: "bensonhurst" }) }).then(res => res.json()); // 遵循state不可变原则,返回新数组而不是修改原对象 setAnimals(animals => animals.map(animal => { return animal._id === updatedAnimal._id ? {...animal, phoneNumber: updatedAnimal.phoneNumber} : animal; })); }
给Animal模型添加子数组功能
第一步修改模型定义
以添加疫苗记录子数组为例,修改Animal.js:
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const AnimalSchema = new Schema({ phoneNumber: {type: String,required: false}, textHistory: {type: String,required: false}, name: {type: String,required: false}, // 新增子数组字段 vaccinationRecords: [{ vaccineName: String, injectDate: Date, hospital: String }] }); const Animal = mongoose.model("Animal", AnimalSchema); module.exports = Animal;
第二步添加子数组新增接口
在server.js里新增路由,用MongoDB的$push操作符往数组添加元素:
app.put('/animal/add-vaccine/:id', async (req, res) => { try { const updatedAnimal = await Animal.findByIdAndUpdate( req.params.id, { $push: { vaccinationRecords: req.body.newVaccine } }, { new: true } // 配置项:返回更新后的完整文档 ); res.json(updatedAnimal); } catch (err) { res.status(500).json({error: err.message}); } })
前端调用该接口时,在请求体传入对应的newVaccine对象即可完成子数组数据新增。
内容的提问来源于stack exchange,提问作者beniboy
相关产品推荐
相关产品推荐

