This is the useState for the Data if I removed this state from the code, it will render fine.
const [cart, setCart] = useState([] as Product[]);
This is the code for Mapping/ Rendering the Data
<SingleProduct {...product} key={index} cart={cart} setCart={() => setCart} />
Types
export type Product = {
name: string;
price: string;
image: string;
id: string;
};
export type Cart = {
cart: Product[];
setCart: (cart: Product[]) => any;
};
export const SingleProduct = ({ cart, setCart }: Cart, { ...product }: Product) => {(
<button onClick={() => { setCart([...cart, product]);}}>
Add to Cart
</button>
<button onClick={setCart(cart.filter((item) => item.id !== product.id))}>
remove from Cart
</button>
)};
Note that if I remove the cart and setCart function, my code works perfectly fine.
I've been debugging this code for more than an hour now, if someone can please help me. It would be a big help!
PS: Still learning TypeScript and I tried making a Shopping Site
CodePudding user response:
I think that the issue is that instead of:
const [cart, setCart] = useState([] as Product[]);
You should do:
const [cart, setCart] = useState<Product[]>([] as Product[]);
Or try:
const [cart, setCart] = useState<Product[]>([]);
CodePudding user response:
Edit: Here's my forked version
Based on your codesandbox, I think I have found your issue.
- Instead of spreading props in
Home.tsx
, try something like this, note, we are passing reference ofsetCart
function. Also, cart is not required to be passed,setState
passes previous state automatically :
{products.map((product, index) => (
<SingleProduct key={index} product={product} setCart={setCart} />
))}
- In your
SingleProduct
, instead of specifying types for each method, you can create a simple interface and pass it toReact.FC
, so all your types will be inferred correctly. Also,setState
has a different signature than what you're using:
interface ISingleProduct {
product: Product;
setCart: React.Dispatch<React.SetStateAction<Product[]>>;
}
export const SingleProduct: React.FC<ISingleProduct> = ({ setCart, product }) => {
- On click functions can be modified as follows (idk why, somehow your
...product
was coming as empty, maybe need to look more closely):
// add to cart
<button
className="add"
onClick={() => {
setCart((prev) => [...prev, product]);
}}
>
// remove from cart
<button
className="add"
onClick={() =>
setCart((cart) => cart.filter((item) => item.id !== product.id))
}
>