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

Fetch发送PATCH请求后端接收数据为null问题排查(Postman正常)

PATCH请求拿不到请求体的修复方案

你的后端接口在Postman中可正常运行,说明接口本身和数据库逻辑没有问题,故障全部出在前端请求代码中,核心问题共3个:

  • 致命拼写错误:fetch的请求头配置字段名应为复数headers,你写成了单数header,导致设置的Content-Type: application/json完全没有生效。后端无法识别请求体为JSON格式,自然解析不到task字段,拿到null/空值。
  • 弹窗输入判断逻辑bug:当用户点击prompt弹窗的「取消」按钮时,返回值是null,此时直接访问alert.length会抛出JS类型错误,中断请求执行;同时没有对输入的前后空格做过滤,容易提交无效内容。
  • 请求路径隐患:使用相对路径api/todos/xxx时,会基于当前页面路由拼接请求地址,若当前页面不在站点根路径,会直接请求到错误的接口地址。

修复后的前端代码

import React from "react";

class UpdateBtn extends React.Component {
    // 将请求方法抽到render外,避免每次渲染重复创建函数
    updateTodo = (todoId, newTask) => {
        // 路径补全前缀斜杠,修正headers为复数形式
        fetch(`/api/todos/${todoId}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ task: newTask })
        })
        .then(res => res.json())
        .then(() => {
            // 等请求成功后再刷新页面,避免请求没发出去就刷新
            window.location.reload()
        })
        .catch(error => console.error(error.message))
    }

    handleUpdate = (e) => {
        const newTask = window.prompt("Update Task:")
        // 覆盖所有无效输入场景:点取消返回null、输入空串、输入全空格
        if (!newTask || !newTask.trim()) {
            return;
        }
        this.updateTodo(e.target.id, newTask.trim())
    }

    render() {
        return (
            <button 
                className="updateBtn"
                id={this.props.id}
                value={this.props.value}
                onClick={this.handleUpdate}
            >
                Update
            </button>
        )
    }
}

export default UpdateBtn;

后端可选优化(提升稳定性)

你当前的后端代码缺少参数校验和错误状态返回,可以补充以下逻辑减少异常:

// 确保已注册JSON解析中间件(Postman能跑通说明已配置,可忽略)
// app.use(express.json())

app.patch('/api/todos/:id', async (req, res) => {
    try {
        const { task } = req.body;
        // 拦截空任务值,避免写入脏数据
        if (!task || !task.trim()) {
            return res.status(400).json({ error: "任务内容不能为空" })
        }
        // 加上RETURNING *可以直接拿到更新后的记录,不需要返回原始请求体
        const updateResult = await pool.query(
            "UPDATE todolist SET task = $1 WHERE id = $2 RETURNING *;",
            [task.trim(), req.params.id]
        )
        res.json(updateResult.rows[0])
    } catch (error) {
        console.error(error.message)
        res.status(500).json({ error: "服务更新失败" })
    }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:12:32