You need to enable JavaScript to run this app. 求解决:Express req.params.itemId返回字面量":itemId"而非实际商品ID
优惠活动
大模型
产品
解决方案
定价
更多

求解决:Express req.params.itemId返回字面量":itemId"而非实际商品ID

问题根源

参数不生效的核心原因是前端请求地址没有做动态插值:
后端定义的路由/add-to-cart/:itemId中,:itemId是Express的路由参数占位符,需要前端发请求时替换成真实的商品id。但你在编写fetch请求时,直接把字面量字符串:itemId硬编码进了请求地址,完全没有把组件props里的真实itemId拼接进去,因此后端收到的req.params.itemId自然就是固定的字符串:itemId,和你控制台的输出结果完全吻合。

修复方案

1. 修正前端fetch的请求地址

把AddToCart组件里的请求地址从硬编码形式:

`http://localhost:8090/auth/add-to-cart/:itemId`

改成动态插值props值的形式:

`http://localhost:8090/auth/add-to-cart/${this.props.itemId}`

修改后发出的请求地址会是类似http://localhost:8090/auth/add-to-cart/650abc123xxx的真实路径,后端才能通过req.params.itemId拿到正确的商品id。

2. 补充避免表单默认行为的逻辑

因为你的按钮嵌在<form>标签内部,点击时默认会触发表单原生提交,和编写的异步fetch逻辑产生冲突,需要给点击事件加阻止默认行为的处理:

// 修改按钮绑定,传入事件对象
<button onClick={(e) => this.addToCart(e)}>Add To Cart</button>

// 在addToCart方法开头阻止表单默认提交
addToCart = async (e) => {
    e.preventDefault();
    // 原有fetch逻辑保持不变
    await fetch(`http://localhost:8090/auth/add-to-cart/${this.props.itemId}`, {
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        credentials: 'include',
    })
    .then(() => { 
        return window.location.replace('/shop');
    })
    .catch(err => console.log(err));
}
之前尝试失效的原因
  • 尝试用req.body获取id不生效:你发的是GET请求,且fetch请求完全没有关联表单内容,form标签内写的hidden输入框的值根本没有被传递到请求体中,req.body自然拿不到任何值;如果要走POST/PATCH请求读req.body的逻辑,需要额外在fetch配置里把序列化后的itemId放到请求body字段,不能依赖表单原生提交。
  • 尝试换query传参不生效:同样是因为前端没有把真实的itemId拼接到query参数中,哪怕后端路由改成了query接收的形式,前端传的还是固定字符串,自然无法获取正确值。
  • 修改请求方法不生效:请求方法只是接口的访问语义,不解决你没有把真实id传到请求里的核心问题。
控制器的逻辑补全

你当前编写的addToCart控制器存在逻辑缺失:拿到正确的item和user之后,没有执行购物车的写入操作,也没有给前端返回响应,哪怕参数正确,接口也会一直挂起到超时。需要补充类似逻辑:

exports.addToCart = async (req, res, next) => {
try {
    const userId = req.session.user._id.toString();
    const user = await User.findById(userId);
    const itemId = req.params.itemId;
    const item = await Item.findById(itemId);
    // 把商品加入用户购物车数组
    user.cart.push({ itemId: item._id });
    await user.save();
    // 给前端返回响应
    res.redirect('/shop');
} catch (err) {
    console.log(err);
    if(!err.statusCode) {
        err.statusCode = 500;
    }
    next(err);
}
};

注:你在组件里写的hidden input是多余的,商品id已经通过props传递到组件内部,直接插值使用即可,不需要靠表单字段携带。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 01:57:04