PUT 400(Bad Request)故障排查:商品库存更新功能异常求助
解决React+Node.js库存更新400 Bad Request问题
核心问题分析
你的代码存在多处参数不匹配、校验逻辑错误和SQL逻辑错误,直接导致400请求失败,具体如下:
- 前后端路由参数名完全不符,后端拿到的参数不是预期值
- 后端校验逻辑同时要求两个互斥参数合法,必然触发校验失败
- SQL更新条件错误,会批量修改所有库存匹配的商品,而非指定商品
- 前端参数有效性判断逻辑写反,未正确校验productID
修复代码
前端dashboard.jsx修改
const Dashboard = () => { const [productStocks, setProductStocks] = useState([]); const handleUpdateStock = ( productID, productStock, quantityToAdd, quantityToRemove ) => { // 优先校验productID有效性 if (productID === undefined || isNaN(productID)) { console.error('productID无效'); return; } // 统一转换为数字类型,避免字符串传参问题 const body = quantityToAdd !== undefined ? { quantityToAdd: Number(quantityToAdd) } : { quantityToRemove: Number(quantityToRemove) }; fetch(`http://localhost:8081/updateStock/${productID}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(body), }) .then((response) => { if (!response.ok) { throw new Error(`HTTP错误! 状态码: ${response.status}`); } return response.json(); }) .then((data) => { console.log('更新响应:', data); setProductStocks((prevProductStocks) => { const updatedProductIndex = prevProductStocks.findIndex( (product) => product.productID === productID ); // 处理找不到商品的边界情况 if (updatedProductIndex === -1) return prevProductStocks; const updatedProductStocks = [...prevProductStocks]; updatedProductStocks[updatedProductIndex] = { ...updatedProductStocks[updatedProductIndex], productStock: data.updatedStock, }; return updatedProductStocks; }); }) .catch((error) => console.error('库存更新失败', error)); }; return ( <div className='div1'> <h1>商品库存</h1> <ul> {productStocks.map((product) => ( <li key={product.productID}> {/* 用唯一productID作为key更可靠 */} <strong>ID:</strong> {product.productID}, <strong>名称:</strong> {product.productName}, <strong>库存:</strong> {product.productStock} <button onClick={() => handleUpdateStock(product.productID, product.productStock, 1)}> <MdAdd className="add-icon" /> </button> <button onClick={() => handleUpdateStock(product.productID, product.productStock, undefined, 1)}> <MdRemove className="remove-icon" /> </button> </li> ))} </ul> </div> ); };
后端app.js修改
app.put('/updateStock/:productID', (req, res) => { const { quantityToAdd, quantityToRemove } = req.body; const productID = req.params.productID; console.log('收到PUT请求:', req.body); // 校验productID是否为正整数 if (isNaN(productID) || Number(productID) <= 0) { return res.status(400).json({ error: '无效的商品ID,必须是正整数。' }); } // 按需校验传入的数量参数 let updateAmount; if (quantityToAdd !== undefined) { if (isNaN(quantityToAdd) || Number(quantityToAdd) < 0) { return res.status(400).json({ error: '无效的新增数量,必须是非负整数。' }); } updateAmount = `+ ${Number(quantityToAdd)}`; } else if (quantityToRemove !== undefined) { if (isNaN(quantityToRemove) || Number(quantityToRemove) < 0) { return res.status(400).json({ error: '无效的减少数量,必须是非负整数。' }); } updateAmount = `- ${Number(quantityToRemove)}`; } else { return res.status(400).json({ error: '必须传入quantityToAdd或quantityToRemove参数。' }); } // 参数化SQL查询,避免注入风险,用productID定位唯一商品 const updateQuery = ` UPDATE product SET productStock = GREATEST(0, productStock ${updateAmount}) WHERE productID = ?`; db.query(updateQuery, [productID], (err, result) => { if (err) { console.error('库存更新失败:', err.message); return res.status(500).json({ error: '服务器内部错误', details: err.message }); } // 查询更新后的最新库存 const selectQuery = 'SELECT productID, productName, productStock FROM product WHERE productID = ?'; db.query(selectQuery, [productID], (err, updatedResult) => { if (err) { console.error('获取更新后库存失败:', err.message); return res.status(500).json({ error: '服务器内部错误', details: err.message }); } if (updatedResult.length === 0) { return res.status(404).json({ error: '未找到指定商品。' }); } return res.json({ success: true, message: '库存更新成功。', updatedStock: updatedResult[0].productStock }); }); }); });
测试步骤
- POSTMAN测试:发送PUT请求到
http://localhost:8081/updateStock/1,请求体传入{"quantityToAdd":1}或{"quantityToRemove":1},验证返回状态和数据 - 前端测试:点击增减按钮后,查看控制台日志,确认库存是否实时更新
内容的提问来源于stack exchange,提问作者Kristian Diaz
相关产品推荐
相关产品推荐

