Reputation: 23
I am working on this e commerce project and I am stuck on the following component:
import React, { useEffect, useState } from 'react';
const Cart = () => {
let [carts, setCarts] = useState([]);
let [price, setPrice] = useState(0);
let [name, setName] = useState('');
useEffect(() => {
fetch('http://localhost:5000/carts').then((response) => {
response.json().then((data) => {
setCarts(data);
})
})
}, []);
async function handleCheckout(id) {
try {
const response = await fetch(`http://localhost:5000/carts/:${id}/checkout`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(id)
})
return response.json();
} catch (error) {
console.error(error.message);
}
};
return (
<>
<div>
{carts.map((cart) => (
<>
{
() => {
if (cart.product_id === 1) {
setName('Deckchair');
setPrice(26);
} if (cart.product_id === 2) {
setName('Stool');
setPrice(10);
} if (cart.product_id === 3) {
setName('Table');
setPrice(77);
}
}}
<div>
<p>Items in your cart:</p>
{console.log(name)}
<p>{name}</p>
<p>Quantity:</p>
<p>{cart.quantity}</p>
<h6>Total price</h6>
{console.log(price)}
<p>£ {cart.quantity * price}</p>
</div>
<p>Complete payment:</p>
<form method="post" action="payment">
<button type="submit" name="payment" onClick={handleCheckout(cart.cart_id)} >Pay Now</button>
</form>
<br />
<p>Copyright 2022 E-Market</p>
</>
))}
</div>
</>
);
};
export default Cart;
I basically need to set a price given the product_id fetched from the database as well as a name as these information are not present in the database.
I was trying to play around it with an if else statement in my JSX return statement ( within an anonymous function) by setting the state according to the product id.
I believe I am missing something but got stuck on how to manage to sort this issue out; Any help would be greatly appreciated.
Upvotes: 0
Views: 99
Reputation: 79
import React, { useEffect, useState } from "react";
const Cart = () => {
const [carts, setCarts] = useState([]);
useEffect(() => {
fetch("http://localhost:5000/carts").then((response) => {
response.json().then((data) => {
setCarts(formatCartsData());
});
});
}, []);
const formatCartsData = (cartsData) => {
return carts.map((cartsData) => {
let cartItem = cartsData;
if (cartsData.product_id === 1) {
cartItem['name'] = "Deckchair";
cartItem['price'] = 26
}
if (cartsData.product_id === 2) {
cartItem['name'] = "Stool";
cartItem['price'] = 10
}
if (cartsData.product_id === 3) {
cartItem['name'] = "Table";
cartItem['price'] = 77
}
return cartItem;
})
}
async function handleCheckout(id) {
try {
const response = await fetch(
`http://localhost:5000/carts/:${id}/checkout`,
{
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(id)
}
);
return response.json();
} catch (error) {
console.error(error.message);
}
}
return (
<>
<div>
{carts.map((cart) => (
<>
<div>
<p>Items in your cart:</p>
{console.log(cart.name)}
<p>{cart.name}</p>
<p>Quantity:</p>
<p>{cart.quantity}</p>
<h6>Total price</h6>
{console.log(cart.price)}
<p>£ {cart.quantity * cart.price}</p>
</div>
<p>Complete payment:</p>
<form method="post" action="payment">
<button
type="submit"
name="payment"
onClick={handleCheckout(cart.cart_id)}
>
Pay Now
</button>
</form>
<br />
<p>Copyright 2022 E-Market</p>
</>
))}
</div>
</>
);
};
export default Cart;
Upvotes: 0
Reputation: 681
Since you are mapping your carts, you can't use only two variables for storing the name and price of your carts. Every cart has it's own values and this way you are overwriting the previous name and price with the last one (and this trigger an endless loop of rendering).
In your case, since it seems you want to assign name and price base on the product_id
you should simply calculate that inside the .map
method before rendering.
In this specific case i would do something like this:
import React, { useEffect, useState } from 'react';
// Removed for shortness
return (
<>
<div>
{carts.map((cart) => {
let _name = ''; // Use some temp variable for the name
let _price = ''; // Use some temp variable for the price
if (cart.product_id === 1) {
_name = 'Deckchair';
_price = 26;
} else if (cart.product_id === 2) {
_name = 'Stool';
_price = 10;
} else if (cart.product_id === 3) {
_name = 'Table';
_price = 77;
}
return (
<>
<div>
<p>Items in your cart:</p>
<p>{_name }</p>
<p>Quantity:</p>
<p>{cart.quantity}</p>
<h6>Total price</h6>
{_price }
</div>
<p>Complete payment:</p>
<form method="post" action="payment">
<button type="submit" name="payment" onClick={handleCheckout(cart.cart_id)} >Pay Now</button>
</form>
<br />
<p>Copyright 2022 E-Market</p>
</>
))})}
</div>
</>
);
};
export default Cart;
There is no need for useState
in your case.
Upvotes: 1
Reputation: 3371
Just an idea but I'm not sure you need to set name and price as state, it looks like you could just look them up during render, something like the following (not tested):
import React, { useEffect, useState } from 'react';
const productInfo = {
1: { name: 'Deckchair', price: 26 },
2: { name: 'Stool', price: 10 },
3: { name: 'Table', price: 77 },
};
const Cart = () => {
let [carts, setCarts] = useState([]);
useEffect(() => {
fetch('http://localhost:5000/carts').then((response) => {
response.json().then((data) => {
setCarts(data);
})
})
}, []);
async function handleCheckout(id) {
try {
const response = await fetch(`http://localhost:5000/carts/:${id}/checkout`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(id)
})
return response.json();
} catch (error) {
console.error(error.message);
}
};
return (
<>
<div>
{carts.map((cart) => {
// do something sensible when info lookup fails
const info = productInfo[cart.product_id] ?? { name: 'Not found', price: 0 };
const { name, price } = info;
return <>
<div>
<p>Items in your cart:</p>
{console.log(name)}
<p>{name}</p>
<p>Quantity:</p>
<p>{cart.quantity}</p>
<h6>Total price</h6>
{console.log(price)}
<p>£ {cart.quantity * price}</p>
</div>
<p>Complete payment:</p>
<form method="post" action="payment">
<button type="submit" name="payment" onClick={handleCheckout(cart.cart_id)} >Pay Now</button>
</form>
<br />
<p>Copyright 2022 E-Market</p>
</>
})}
</div>
</>
);
};
export default Cart;
A possible alternative might be to merge the info into the carts data at the point you grab the data. e.g. something like:
useEffect(() => {
fetch('http://localhost:5000/carts').then((response) => {
response.json().then((data) => {
setCarts(
data.map((cart) => ({ ...cart, ...productInfo[cart.product_id] }))
);
})
})
}, []);
Upvotes: 1