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;
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 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');
}
});
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
my bad. my frontend put multple
thus rendering it 4 times
Use set to remove duplicate values.