React调用axios.delete删除数据库条目时总是移除列表最后一个元素问题
问题根因
- 所有弹窗共用同一个状态变量:你在
map遍历商品列表的逻辑里给每个商品都生成了一个Dialog组件,但所有Dialog都绑定了同一个open状态。点击任意删除按钮会把open设为true,所有弹窗同时打开,最后一个商品的弹窗层级最高会覆盖在最上层,你点击确认按钮时实际触发的是最后一个商品的删除逻辑,所以每次都会删列表最后一条。 - 删除接口硬编码错误:
axios.delete的请求地址里把要删除的id写死成了1,不管你传什么id,接口实际只会请求删除id为1的商品。 - 冗余的axios导入:顶部已经通过
import引入了axios,组件内部的const axios = require('axios')是无效冗余代码。 - 列表更新存在闭包陷阱:直接用
products.filter更新状态,在异步场景下可能拿到旧的列表数据,导致更新异常。
修复步骤
- 把Dialog从循环逻辑中移出,全局只保留一个弹窗,新增
activeDeleteId状态存储当前要删除的商品id - 点击删除按钮时先把当前商品id存入
activeDeleteId,再打开弹窗 - 替换删除接口的硬编码id为动态参数
- 删掉冗余的axios导入,列表更新改用函数式写法
修正后完整代码
import {useState, useEffect} from "react" import React from "react" import axios from 'axios' import AddProduct from './AddProduct' import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; function Products() { const [products,setProducts] = useState([]) const [open, setOpen] = useState(false) // 新增状态存储当前要删除的商品id const [activeDeleteId, setActiveDeleteId] = useState(null) const handleClickOpen = (id) => { setActiveDeleteId(id) setOpen(true); }; const handleClose = () => { setActiveDeleteId(null) setOpen(false); }; const addProduct = async (newProduct) => { const response = await axios.post('https://fakestoreapi.com/products', newProduct); console.log(response) setProducts([...products,response.data]) } const deleteProduct = (id) => { console.log(id) // 替换硬编码的id为传入的动态id axios.delete(`https://fakestoreapi.com/products/${id}`).then(() => { // 改用函数式更新避免闭包问题 setProducts(prev => prev.filter(prod => prod.id !== id)) handleClose() }).catch((err) => console.log(err)) } useEffect(() => axios({ method: "get", url: "https://fakestoreapi.com/products" }).then((response) => setProducts(response.data)) .catch((err) => console.log(err)),[] ) console.log(products) return ( <div> <h2>Add new product</h2> <AddProduct onSubmit={addProduct} /> <div className="products-list"> {products.map((product) => <div key={product.id} className="product-box"> <p>Id: {product.id}</p> <p>Title: {product.title}</p> <p>Price: {product.price}</p> <p>Category: {product.category}</p> <p>Image: {product.image}</p> <Button variant="outlined" onClick={() => handleClickOpen(product.id)}> Delete </Button> </div>)} </div> {/* 弹窗移到循环外,全局只保留一个 */} <Dialog open={open} onClose={handleClose} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > <DialogTitle id="alert-dialog-title"> {"Usunąć ten produkt?"} </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> Ta operacja nie będzie odwracalna </DialogContentText> </DialogContent> <DialogActions> <Button onClick={handleClose}>NIE</Button> <Button onClick={() => { deleteProduct(activeDeleteId); }} autoFocus> TAK </Button> </DialogActions> </Dialog> </div> ) } export default Products;
内容的提问来源于stack exchange,提问作者sunny
相关产品推荐
相关产品推荐

