React+JSON Server文章发布/更新问题:字段丢失、跳转失效求助
React提交JSON Server数据异常及跳转失效问题解决
一、提交仅生成ID,字段未写入数据库的问题
核心错误点
- 请求头格式错误:
fetch的headers中contentType应写为Content-Type(首字母必须大写),且值为application/json。JSON Server依赖正确的请求头解析JSON数据,原写法导致服务端无法识别请求体,因此仅生成ID,忽略其他字段。 - 图片字段类型不兼容:当前
image状态存储的是File对象,JSON Server仅支持字符串类型数据,直接提交File对象会被忽略。 - 表单输入未绑定value:输入框仅通过
onChange更新状态,但未设置value属性,属于非受控组件,可能导致状态与输入值不同步。 - 日期输入未关联状态:页面上的日期输入框未绑定
postdate状态,提交的始终是初始值,无法修改。
修复方案
1. 修正请求头与跳转逻辑
const formSubmit = (e)=> { e.preventDefault(); // 将图片转为base64字符串(无需外部存储时的方案) const handleImageUpload = (file) => { if (!file) return Promise.resolve(""); return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target.result); reader.readAsDataURL(file); }); }; handleImageUpload(image).then((imageBase64) => { const docs = { image: imageBase64, posttitle, postdate, postdesc, }; fetch("http://localhost:8005/posts", { method: "POST", headers: { "Content-Type": "application/json" }, // 修正请求头 body: JSON.stringify(docs), }) .then(res => { if (res.ok) navigate("/home"); // 修复跳转方式 }) .catch(err => console.error("提交失败:", err)); // 增加错误捕获 }); }
2. 绑定表单输入的value属性
// 标题输入框 <input type="text" value={posttitle} // 绑定状态值 className="writeinput" onChange={(e) => setPostTitle(e.target.value)} placeholder="输入文章标题" autoFocus /> // 内容输入框 <textarea value={postdesc} // 绑定状态值 onChange={(e) => setPostDesc(e.target.value)} className="writeinput writetext" placeholder="输入文章内容" ></textarea> // 日期输入框(补充状态绑定) <input type="text" value={postdate} onChange={(e) => setPostDate(e.target.value)} placeholder="输入日期(格式:20-29-2022)" />
3. 移除图片标签无效的onChange事件
预览图片的img标签无需onChange,直接删除该属性:
<img className="writeimage" alt="postimage" src={URL.createObjectURL(image)} />
二、提交后跳转至首页失效的问题
useNavigate的用法错误:useNavigate返回的是直接调用的函数,而非带push方法的对象。原代码中navigate.push("/home")是useHistory的用法,改为直接调用navigate("/home")即可。
完整修改后的Write组件代码
import { useState } from "react"; import "./write.css"; import { useNavigate } from "react-router-dom"; export default function Write() { const [image, setImage] = useState(); const [posttitle, setPostTitle] = useState(""); const [postdesc, setPostDesc] = useState(""); const [postdate, setPostDate] = useState("20-29-2022"); // 匹配现有数据格式 const navigate = useNavigate(); const formSubmit = (e)=> { e.preventDefault(); if (!posttitle || !postdesc) return; // 简单校验 const handleImageUpload = (file) => { if (!file) return Promise.resolve(""); return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target.result); reader.readAsDataURL(file); }); }; handleImageUpload(image).then((imageBase64) => { const docs = { image: imageBase64, posttitle, postdate, postdesc, }; fetch("http://localhost:8005/posts", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(docs), }) .then(res => { if (res.ok) navigate("/home"); }) .catch(err => console.error("提交失败:", err)); }); } return ( <div className="write"> <form className="writeform" onSubmit={formSubmit}> <div> <input type="text" value={postdate} onChange={(e) => setPostDate(e.target.value)} placeholder="输入日期(格式:20-29-2022)" /> </div> <div className="image_container"> {image && ( <div> <img className="writeimage" alt="postimage" src={URL.createObjectURL(image)} /> </div> )} </div> <div className="writeformgroup"> <label htmlFor="fileinput"> <i className="writeicon fa-solid fa-plus"></i> </label> <input id="fileinput" type="file" onChange={(e) => setImage(e.target.files[0])} style={{ display: "none" }} /> <input type="text" value={posttitle} className="writeinput" onChange={(e) => setPostTitle(e.target.value)} placeholder="输入文章标题" autoFocus /> </div> <div className="writeformgroup"> <textarea value={postdesc} onChange={(e) => setPostDesc(e.target.value)} className="writeinput writetext" placeholder="输入文章内容" ></textarea> </div> <button className="writesubmit">Publish</button> </form> <p>{posttitle}</p> </div> ); }
补充说明
- 若需存储图片URL而非base64,可将图片上传至云存储(如阿里云OSS、Firebase Storage),再将返回的URL存入JSON Server。
- 编辑功能的
fetch请求需同步修正Content-Type头,且JSON.stringify()中要传入完整的更新数据对象,原代码中该部分为空,无法完成更新。
内容的提问来源于stack exchange,提问作者Deulo
相关产品推荐
相关产品推荐

