You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:20:39