React simple delete from the database – always removing last element



I have a problem when doing some React exercises with DELETING an item. When I do it like this, using axios.delete and .filter using a function deleteProduct which is activated when I confirm the action, it always takes as an id the id of the last element in list, so e.g. when I delete 3rd item, it deletes last, so 20th, if 20th is removed, it removes 19th next. I don’t know where the problem is, because when I do .map, the product.id should be readable for each element, shouldn’t it?

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 axios = require('axios')
    const [products,setProducts] = useState([])

    const [open, setOpen] = useState(false)
    const handleClickOpen = () => {
        setOpen(true);
    };

    const handleClose = () => {
        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)
        axios.delete('https://fakestoreapi.com/products/1').then(() => setProducts(products.filter(prod => prod.id !== id)))
            .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}>
                            Delete
                        </Button>
                        <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(product.id);
                                    handleClose();
                                    
                                }} autoFocus>
                                    TAK
                                </Button>
                            </DialogActions>
                        </Dialog>
                    </div>)}

            </div>
        </div>
    )

}
export default Products;

Answer

Looks like you are always clicking the TAK button of the last item. It makes no difference which “DELETE” button you click,as the button does the same regardless of which one you click on, since it doesn’t use the product.id

Easiest approach (from where you are at) is probably to change your useState from a boolean, to an integer and store the id of the product in open.

const [open, setOpen] = useState(-1)

Then pass the product.id to the handleClickOpen

const handleClickOpen = (id) => {
    setOpen(id);
};
...
<Button variant="outlined" onClick={() => handleClickOpen(product.id)}>
    Delete
</Button>

Then in the render, render the dialog if the open matches product.id

 <Dialog
       open={open===product.id}

and fix up things like handleClose, too.

const handleClose = () => {
    setOpen(-1);
};


Source: stackoverflow