skip to Main Content

I am currently building a simple eccomerce platform using react, express js and mysql as database.
now as i am retrieving data from the database to produce the products it does replicated it self into multiple instances like, product 1 then it will be displayed as 3 products with the same name and ID

this is the code

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const ProductCard = ({ product }) => {
    const [isEditing, setIsEditing] = useState(false);
    const [editedProduct, setEditedProduct] = useState({});

    useEffect(() => {
        console.log('ProductCard mounted with product:', product);
        return () => {
            console.log('ProductCard unmounted');
        };
    }, [product]);

    if (!product) {
        return <div>Product data is not available</div>;
    }

    const handleEditClick = () => {
        setIsEditing(true);
        setEditedProduct(product); // Pre-fill form with current product data
    };

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setEditedProduct(prevState => ({
            ...prevState,
            [name]: value,
        }));
    };

    const handleUpdate = async () => {
        try {
            await axios.put(`http://localhost:5000/products/${product.product_id}`, editedProduct);
            alert('Product updated successfully');
            setIsEditing(false);
        } catch (error) {
            console.error('Error updating product:', error);
            alert('Error updating product');
        }
    };

    return (
        <div className='procard'>
            <div className='productimg' style={{ width: '100%', height: '65%' }}>
                <img
                    style={{ width: '98%', height: '100%', objectFit: 'cover' }}
                    src={product.image_url || 'https://via.placeholder.com/150'}
                    alt={product.product_name || 'Product Image'}
                />
            </div>
            <div className='productdesc' style={{ width: '100%', height: '35%' }}>
                {isEditing ? (
                    <div className='product-edit'>
                        <input
                            type='text'
                            name='product_name'
                            value={editedProduct.product_name || ''}
                            onChange={handleInputChange}
                            placeholder='Product Name'
                        />
                        <textarea
                            name='description'
                            value={editedProduct.description || ''}
                            onChange={handleInputChange}
                            placeholder='Description'
                        />
                        <input
                            type='number'
                            name='quantity'
                            value={editedProduct.quantity || ''}
                            onChange={handleInputChange}
                            placeholder='Quantity'
                        />
                        <input
                            type='number'
                            name='size'
                            value={editedProduct.size || ''}
                            onChange={handleInputChange}
                            placeholder='Size (ml)'
                        />
                        <button onClick={handleUpdate}>Update Product</button>
                        <button onClick={() => setIsEditing(false)}>Cancel</button>
                    </div>
                ) : (
                    <div className='product-data'>
                        <p>{product.product_name || 'No product name'}</p>
                        <div className='order-options'>
                            <button>Add to Cart</button>
                            <button>Buy Now</button>
                            <button onClick={handleEditClick}>Edit Product</button>
                        </div>
                    </div>
                )}
            </div>
        </div>
    );
};

const ProductList = () => {
    const [products, setProducts] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        console.log('ProductList mounted');
        const fetchProducts = async () => {
            try {
                const response = await axios.get('http://localhost:5000/products');
                if (response.status === 200) {
                    console.log('Fetched products:', response.data);
                    
                    const uniqueProducts = Array.from(new Map(response.data.map(product => [product.product_id, product])).values());
                    setProducts(uniqueProducts);
                } else {
                    throw new Error(`Unexpected response status: ${response.status}`);
                }
            } catch (error) {
                console.error('Error fetching products:', error.response ? error.response.data : error.message);
                setError('Error fetching products: ' + (error.response ? error.response.data : error.message));
            } finally {
                setLoading(false);
            }
        };

        fetchProducts();
        return () => {
            console.log('ProductList unmounted');
        };
    }, []); // Empty dependency array to ensure effect runs only once on mount

    if (loading) {
        return <div>Loading...</div>;
    }

    if (error) {
        return <div>{error}</div>;
    }

    return (
        <div className='product-list'>
            {products.length > 0 ? (
                products.map(product => (
                    <ProductCard key={product.product_id} product={product} />
                ))
            ) : (
                <div>No products available</div>
            )}
        </div>
    );
};

export default ProductList;

this is the server side console running

i did try to console log it so that i could see if the query is working and has no duplication of data so far it does not replicate

however on my fronend this is the issue

this is the frontend image where the problem is

this is my backend query


app.get('/products', async (req, res) => {
    try {
        const [rows] = await db.query('SELECT * FROM product');
        const uniqueProducts = Array.from(new Map(rows.map(product => [product.product_id, product])).values());
        console.log('Fetched unique products:', uniqueProducts);
        res.json(uniqueProducts);
    } catch (error) {
        console.error('Error fetching products:', error);
        res.status(500).send('Error fetching products');
    }
});

i dont know why it requested multiple api

ithink this is the code that triggers mulitple api request

 useEffect(() => {
    const fetchProducts = async () => {
        try {
            const response = await axios.get('http://localhost:5000/products');
            if (response.status === 200) {
              
                const uniqueProducts = Array.from(new Set(response.data.map(p => p.product_id)))
                    .map(id => response.data.find(p => p.product_id === id));
                setProducts(uniqueProducts);
            } else {
                throw new Error(`Unexpected response status: ${response.status}`);
            }
        } catch (error) {
            setError('Error fetching products: ' + (error.response ? error.response.data : error.message));
        } finally {
            setLoading(false);
        }
    };

    
    fetchProducts();
}, []); 

i wanted that whenever i display the data from the db there will be no duplication of data

2

Answers


  1. Chosen as BEST ANSWER

    my bad. my frontend put multple multiple product card

    thus rendering it 4 times


  2. Use set to remove duplicate values.

    const products = []
    const uniqueProducts = [new Set(...products)]
    console.log(uniqueProducts) // No duplicate value
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search