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

React+Express POST存JSON成功却报net::ERR_CONNECTION_REFUSED错误求助

问题排查:React客户端POST请求数据保存成功但出现net::ERR_CONNECTION_REFUSED错误

使用React客户端+Express服务端开发,通过POST方法提交数据到服务端并保存到JSON文件,数据已成功保存,但控制台抛出net::ERR_CONNECTION_REFUSED错误。

客户端代码

import { useState, useRef } from "react";

import NavBar from "./NavBar";

const AddMovie = () => {
  const [movieData, setMovieData] = useState({});
  const clearFormInput = useRef(null);

  const formDataHandler = (e) => {
    setMovieData({
      ...movieData,
      [e.target.name]: e.target.value,
    });
  };

  const submitDataHandler = (e) => {
    e.preventDefault();

    fetch("http://localhost:3001/add", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(movieData),
    })
      .then((response) => {
        return response.json();
      })
      .then((data) => console.log(data))
      .catch((error) => console.error(error));

    clearFormInput.current.reset();
  };

  return (
    <div>
      <NavBar />
      <form
        onSubmit={submitDataHandler}
        ref={clearFormInput}
        className="m-auto p-5 w-[30rem] bg-blue-400 relative top-60 transform -translate-y-1/2"
      >
        <div className="flex flex-col">
          <label htmlFor="title">Movie Title</label>
          <input
            onChange={formDataHandler}
            type="text"
            name="title"
            id="title"
            required
          />
        </div>
        <div className="flex flex-col">
          <label htmlFor="whereToWatch">Where do we find it?</label>
          <input
            onChange={formDataHandler}
            type="text"
            name="whereToWatch"
            id="whereToWatch"
            placeholder="e.g. NetFlix"
            required
          />
        </div>
        <div className="flex flex-col">
          <label htmlFor="description">Tell us about the movie</label>
          <textarea
            onChange={formDataHandler}
            name="description"
            id="description"
            type="text"
            required
          />
        </div>
        <button className="my-4 p-3 bg-blue-950 text-white rounded-md">
          Share Movie
        </button>
      </form>
    </div>
  );
};

export default AddMovie;

服务端代码

const express = require("express");
const cors = require("cors");
const uuid = require("uuid");

const path = require("path");
const fs = require("fs");

const app = express();

app.use(
  cors({
    origin: "http://localhost:5174",
  })
);
app.use(express.json());

app.get("/", (req, res) => {
  res.send("server is running...");
});

app.post("/add", (req, res) => {
  const movieData = req.body;

  console.log(movieData)
  movieData.id = uuid.v4();

  const filePath = path.join(__dirname, "data", "movies.json");

  const fileData = fs.readFileSync(filePath);
  const existingMovies = JSON.parse(fileData);
  existingMovies.push(movieData);

  fs.writeFileSync(filePath, JSON.stringify(existingMovies));
});

app.listen(3001);

问题根源与修复方案

问题核心

服务端的/addPOST接口处理完数据保存逻辑后,未向客户端返回任何响应,导致客户端的fetch请求长期处于等待状态,最终超时触发net::ERR_CONNECTION_REFUSED错误。尽管数据已成功写入文件,但请求周期未正常结束,客户端无法收到预期响应。

修复步骤

  1. 在服务端的POST接口中添加响应语句,结束请求周期:
app.post("/add", (req, res) => {
  const movieData = req.body;

  console.log(movieData)
  movieData.id = uuid.v4();

  const filePath = path.join(__dirname, "data", "movies.json");

  const fileData = fs.readFileSync(filePath);
  const existingMovies = JSON.parse(fileData);
  existingMovies.push(movieData);

  fs.writeFileSync(filePath, JSON.stringify(existingMovies));
  
  // 添加成功响应,告知客户端请求完成
  res.status(201).json({ message: "电影数据保存成功", movie: movieData });
});
  1. 额外验证点
  • 确认服务端运行端口为3001,客户端请求地址http://localhost:3001/add无误
  • 确认cors配置的origin值与客户端实际运行端口(5174)一致,避免跨域拦截
  • 确保服务端项目下的data目录及movies.json文件存在,否则fs模块会抛出文件读取错误,导致请求异常

内容的提问来源于stack exchange,提问作者Sam Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:00:27