Home > front end >  Data not rendering if I Include a State as my Props; React and TypeScript
Data not rendering if I Include a State as my Props; React and TypeScript

Time:04-09

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.

  1. Instead of spreading props in Home.tsx, try something like this, note, we are passing reference of setCart 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} />
))}
  1. In your SingleProduct, instead of specifying types for each method, you can create a simple interface and pass it to React.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 }) => {
  1. 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))
  }
>
  • Related