React中使用json-server提交表单仅生成ID,字段未正常存储
问题描述
我正在编写React代码并试用json-server,实现带标题的笔记创建及存储功能,用json-server模拟REST API。通过curl或httpie发送POST请求能正常存储笔记的title和content字段,但使用React表单提交时,仅生成ID,title和content为空。以下是相关代码、命令及测试结果:
React组件代码
import { useState } from "react"; export default function () { const [title, setTitle] = useState('title'); const [content, setContent] = useState('content here'); const [errorMessage, setErrorMessage] = useState(''); let handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); try { let res = await fetch("http://localhost:3001/notes", { method: "post", body: JSON.stringify({ title: title, content: content, }) }) let resJson = await res.json(); console.log(resJson); if (res.status == 201) { setTitle('') setContent('') } else { setErrorMessage(`something went wrong, ${res.status}`) } } catch(err) { console.log(err); } } return ( <form onSubmit={handleSubmit}> <div className="flex flex-col"> <input type="text" value={title} onChange={e => setTitle(e.target.value)} className="border-2 border-gray"/> <textarea className="border-2 border-gray" value={content} onChange={(event) => setContent(event.target.value)} autoFocus rows={5} wrap="soft"/> <button type="submit">Add</button> {errorMessage && <p>{errorMessage}</p>} </div> </form> ); }
json-server启动命令
json-server --watch db.json --port 3001
正常请求示例(curl/httpie)
http post localhost:3001/notes --raw '{ "title": "A", "content": "B" }'
或
http post localhost:3001/notes title="test" content="test content"
正常请求后的查询结果
执行查询命令:
http localhost:3001/notes
返回结果:
[ { "content": "test content", "id": 11, "title": "test" }, { "content": "B", "id": 15, "title": "A" } ]
React表单提交后的异常结果
数据库中仅新增如下内容:
{ "id": 16 }
问题原因与解决方法
问题出在fetch请求缺少Content-Type请求头。当你用JSON.stringify把数据转为JSON格式后,必须明确告诉服务器请求体是JSON类型,否则json-server无法解析请求体中的字段,只会生成默认的ID。
修改后的handleSubmit函数需添加请求头配置:
let handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); try { let res = await fetch("http://localhost:3001/notes", { method: "post", headers: { 'Content-Type': 'application/json', // 新增这行配置 }, body: JSON.stringify({ title: title, content: content, }) }) let resJson = await res.json(); console.log(resJson); if (res.status == 201) { setTitle('') setContent('') } else { setErrorMessage(`something went wrong, ${res.status}`) } } catch(err) { console.log(err); } }
说明:curl/httpie会自动根据请求内容设置合适的Content-Type(比如发送JSON时自动设为application/json,发送表单参数时设为application/x-www-form-urlencoded),但fetch默认不会添加该请求头,因此必须手动指定。
内容的提问来源于stack exchange,提问作者YotKay
相关产品推荐
相关产品推荐

