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

React在Heroku中向Node.js服务器Fetch数据无请求数据问题排查

Heroku上React向Node.js服务器POST请求无数据的问题解决

问题场景

我在Heroku部署了React前端和Node.js后端,前端通过POST请求向服务器发送数据,但后端打印req时看不到任何请求相关数据。怀疑是Express配置出了问题(为适配Heroku加了express.static(),之前用的express.json()),另外React项目的package.json里proxy还是设置成http://localhost:7000。

前端代码

const { name } = e.target.elements;
let details = {
    name: name.value,
};
let response = await fetch("/post", {
    method: "POST",
    headers: {
        "Content-Type": "application/json;charset=utf-8",
    },
    body: JSON.stringify(details),
});

服务器端代码

if(process.env.NODE_ENV === "production") {
    app.use(express.static('../client/build'));
    app.get('*', (req, res) => {
        req.sendFile(path.resolve('client/build/index.html', { root: "../" }));
    });
}

app.post("/post", async (req, res) => {
    const queryRes = await searchFromQuery(req.body.name);

    res.json({
        status: queryRes.isFound ? "found" : "notFound", teaminfo: {
            name: queryRes.name,
            number: queryRes.number,
            avgScore: queryRes.avgScore,
            predictedScore: queryRes.predictedScore,
        }
    });
});

app.listen(PORT, console.log(`Server started on port ${PORT}`));

app.get("/", function(req, res) {
    res.sendFile('client/build/index.html', { root: "../" });
});

问题原因及解决方案

1. 缺失JSON请求体解析中间件

你的服务器代码里没配置express.json()中间件,导致Express无法解析POST请求的JSON格式请求体,req.body自然是undefined。不管是开发还是生产环境,这个中间件都必须加,而且要放在所有路由定义之前:

// 放在所有路由配置最前面
app.use(express.json());

2. 路由顺序错误

你把生产环境的app.get('*')放在了API路由前面,这会导致所有请求(包括/post接口)都被重定向到index.html,API根本不会被触发。正确的顺序应该是:

  • 先配置中间件
  • 再定义所有API路由
  • 最后配置生产环境的静态文件托管和兜底路由

3. Heroku环境下的Proxy无效

React项目里的proxy字段只在本地开发环境(npm start)生效,生产环境部署到Heroku后完全没用——因为此时React静态文件是由Express托管的,请求直接走Express,不存在跨域代理的需求。

修正后的服务器代码

const express = require('express');
const path = require('path');
const app = express();

// 1. 先配置JSON解析中间件
app.use(express.json());

// 2. 定义API路由
app.post("/post", async (req, res) => {
    const queryRes = await searchFromQuery(req.body.name);

    res.json({
        status: queryRes.isFound ? "found" : "notFound", 
        teaminfo: {
            name: queryRes.name,
            number: queryRes.number,
            avgScore: queryRes.avgScore,
            predictedScore: queryRes.predictedScore,
        }
    });
});

// 3. 生产环境静态文件托管和兜底路由
if(process.env.NODE_ENV === "production") {
    app.use(express.static(path.resolve(__dirname, '../client/build')));
    
    // 所有非API请求返回index.html
    app.get('*', (req, res) => {
        res.sendFile(path.resolve(__dirname, '../client/build/index.html'));
    });
}

// 原来的app.get("/")可以删掉,*路由已经覆盖了这个场景
const PORT = process.env.PORT || 7000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

4. 端口注意事项

Heroku会动态分配端口,所以服务器必须用process.env.PORT,你的代码已经做到了这点。前端请求时直接用相对路径/post就行,不用指定端口,Heroku会自动处理端口映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:09:21