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

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);
});

关键修复说明

  1. 前端输入处理:修正onChange事件逻辑,确保状态正确接收输入值,并添加输入校验
  2. 请求状态处理:为所有Axios请求添加then/catch,捕获错误并反馈,同时在操作成功后重新拉取数据更新列表
  3. 唯一性删除:使用数据库表的id字段作为删除条件,避免因名称重复导致的误删
  4. 后端参数传递:修复SQL查询的参数格式,确保与SQL语句中的占位符匹配
  5. 响应反馈:后端接口添加状态码和JSON响应,让前端明确知道请求结果
  6. useEffect优化:添加空依赖数组,避免重复发起GET请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:50:51