PERN栈前端PUT请求Postman正常但调用失效,编辑Todo后值为null
问题根因
你的后端接口本身没有故障,Postman可正常调用已经排除后端问题,故障出在前端state类型不匹配导致传参错误:
- 初始化
descriptionstate时,你传入的是整个todo对象,结构为{id: number, todo: string} - 但输入框的
onChange回调里,你直接执行setDescription(e.target.value),直接把description从对象类型覆盖成了字符串类型,原对象的todo属性直接丢失,此时访问description.todo会得到undefined,序列化后传给后端的字段为空,最终数据库存入null。 - 你控制台打印的
description {id: 56, todo: null}是组件首次渲染时的初始值,输入修改后state已经变成字符串,只是你没有触发更新后的打印而已,并非editText函数未执行。
修复方法
推荐用更简洁的第一种写法,直接让state存待编辑的文本字符串即可:
- 把useState初始值改为取todo对象的todo字段:
const [description, setDescription] = useState(todo.todo) - 输入框的value属性直接绑定
value={description},不需要取.todo属性 - 请求体保持
const body = { description }即可,此时传给后端的结构和Postman测试的结构完全一致。
修改后的完整组件代码:
export default function EditTodo({ todo }) { // 直接初始化state为待编辑的文本内容 const [description, setDescription] = useState(todo.todo); console.log("todos", todo); console.log("current edit text:", description); const editText = async (id) => { try { const body = { description }; await fetch(`http://localhost:5000/todos/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); window.location = "/"; } catch (error) { console.error(error.message); } }; return ( <Fragment> <button type="button" className="btn btn-warning" data-toggle="modal" data-target="#myModal" > Edit </button> <div className="modal" id="myModal"> <div className="modal-dialog"> <div className="modal-content"> <div className="modal-header"> <h4 className="modal-title">Edit Todo</h4> <button type="button" className="close" data-dismiss="modal" ></button> </div> <div className="modal-body"> <input type="text" className="form-control" value={description} onChange={(e) => setDescription(e.target.value)} /> </div> <div className="modal-footer"> <button type="button" className="btn btn-warning" data-dismiss="modal" onClick={() => editText(todo.id)} > Edit </button> <button type="button" className="btn btn-danger" data-dismiss="modal" > Close </button> </div> </div> </div> </div> </Fragment> ); }
如果你需要保留整个todo对象在state中,只需要修改两处:
- onChange回调改为更新对象的指定字段:
onChange={(e) => setDescription(prev => ({...prev, todo: e.target.value}))} - 构造请求体时取对象内的文本值:
const body = { description: description.todo }
改完后可以在editText函数内打印body确认结构,只要传参和Postman测试的结构一致,就能正常更新。
内容的提问来源于stack exchange,提问作者Zulfiya Yumagulova
相关产品推荐
相关产品推荐

