'Data not rendering if I Include a State as my Props; React and TypeScript
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
Solution 1:[1]
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 ofsetCartfunction. Also, cart is not required to be passed,setStatepasses 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,setStatehas 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
...productwas 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))
}
>
Solution 2:[2]
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[]>([]);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | boxdox |
| Solution 2 | jcobo1 |
