React前端向SQL数据库插入/删除数据无响应问题求助
问题排查与修复方案
前端代码问题及修复
核心错误点
useEffect未添加依赖数组,会无限重复发起GET请求,引发状态异常- 输入框的
onChange事件处理错误,直接传递setName/setSrc会导致状态接收的是事件对象而非输入值 insertRow中Axios请求未处理then/catch,无法捕获请求错误,也未更新前端数据列表deleteRow未接收参数,且URL拼接使用逗号运算符导致参数错误,同时未利用唯一标识(如id)进行删除操作
修复后的前端代码
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import Helmet from 'react-helmet'; export default function Products() { const [rows, setRows] = useState([]); const [name, setName] = useState(''); const [src, setSrc] = useState(''); // 仅在组件挂载时获取一次数据 useEffect(() => { fetchProducts(); }, []); // 封装获取数据函数,便于复用 const fetchProducts = () => { axios.get('/products/get') .then(res => { setRows(res.data); }).catch(err => { console.error('获取数据失败:', err); }); }; const insertRow = () => { if (!name || !src) { console.warn('名称和图片地址不能为空'); return; } axios.post('/products/insert', { name: name, image: src }) .then(() => { // 插入成功后重新获取数据 fetchProducts(); // 清空输入框 setName(''); setSrc(''); }) .catch(err => { console.error('插入失败:', err); }); }; // 根据id删除,确保唯一性 const deleteRow = (productId) => { axios.delete(`/products/delete/${productId}`) .then(() => { // 删除成功后重新获取数据 fetchProducts(); }) .catch(err => { console.error('删除失败:', err); }); }; return ( <> <Helmet> <title>Title | products</title> </Helmet> <div className="pt-36 sm:pt-44 pb-20 md:pb-48 max-w-[1200px] mx-5 lg:mx-auto"> <input className="border-2 border-black p-1" type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="产品名称" /> <input className="border-2 border-black p-1" type="text" value={src} onChange={(e) => setSrc(e.target.value)} placeholder="图片地址" /> <button className="border-2 border-l-0 border-black p-1" onClick={insertRow}>Submit</button> {rows.map((row) => { return ( <div key={row.id}> {/* 使用数据库id作为key,避免index导致的问题 */} <p>{row.name}</p> <img src={row.image} alt={row.name} style={{width: '100px'}} /> <button onClick={() => deleteRow(row.id)}>Delete</button> </div> ) })} </div> </> ); };
后端代码问题及修复
核心错误点
- 插入接口中,SQL参数传递错误:将整个对象传入
db.query,而SQL需要的是name和image两个独立值 - 插入和删除接口均未向前端返回响应,导致前端无法判断请求状态
- 删除接口使用
name作为删除条件,存在重复数据误删风险,应使用唯一标识id - 删除接口的URL参数设计不合理,无法正确接收前端传递的id
修复后的后端代码
const express = require('express'); const cors = require('cors'); const db = require('./config/db'); const app = express(); const PORT = process.env.PORT || 8080; app.use(express.json()); app.use(cors()); //#region Products table app.get('/products/get', (req, res) => { const selectAll = 'SELECT * FROM products'; db.query(selectAll, (err, rows) => { if (err) { console.error('查询失败:', err); return res.status(500).json({error: '查询数据失败'}); } res.json(rows); }); }); //Insert into database app.post('/products/insert', (req, res) => { const { name, image } = req.body; if (!name || !image) { return res.status(400).json({error: '名称和图片地址不能为空'}); } const insertRow = "INSERT INTO products (name, image) VALUES (?, ?)"; db.query(insertRow, [name, image], (err, result) => { if (err) { console.error('插入失败:', err); return res.status(500).json({error: '插入数据失败'}); } console.log(`插入成功,ID: ${result.insertId}`); res.json({message: '插入成功', insertId: result.insertId}); }); }); //Delete from database app.delete('/products/delete/:id', (req, res) => { const productId = req.params.id; const deleteRow = "DELETE FROM products WHERE id = ?"; db.query(deleteRow, [productId], (err, result) => { if (err) { console.error('删除失败:', err); return res.status(500).json({error: '删除数据失败'}); } if (result.affectedRows === 0) { return res.status(404).json({error: '未找到该产品'}); } console.log(`删除成功,ID: ${productId}`); res.json({message: '删除成功'}); }); }); //#endregion app.listen(PORT, () => { console.log('Server started on port ' + PORT); });
关键修复说明
- 前端输入处理:修正
onChange事件逻辑,确保状态正确接收输入值,并添加输入校验 - 请求状态处理:为所有Axios请求添加
then/catch,捕获错误并反馈,同时在操作成功后重新拉取数据更新列表 - 唯一性删除:使用数据库表的
id字段作为删除条件,避免因名称重复导致的误删 - 后端参数传递:修复SQL查询的参数格式,确保与SQL语句中的占位符匹配
- 响应反馈:后端接口添加状态码和JSON响应,让前端明确知道请求结果
- useEffect优化:添加空依赖数组,避免重复发起GET请求
内容的提问来源于stack exchange,提问作者Josh Haywood
相关产品推荐
相关产品推荐

