Home > Software engineering >  ReactJs handleAddProduct is not a function at onClick
ReactJs handleAddProduct is not a function at onClick

Time:07-22

I'm finishing a page with shopping cart. I have a function that adds products to the cart and that works in other sections of the page perfectly. The problem is that on the home page the function tells me:

handleAddProduct is not a function at onClick.

Here I leave the components that are causing problems

App.js

const [cartItems, setCartItems] = useState([]);

  const handleAddProduct = (product) => {
    toast('✔️ Producto añadido')
    console.log('Producto seleccionado')
    const ProductExist = cartItems.find((item) => item.id === product.id);
    if(ProductExist){
      setCartItems(
        cartItems.map((item)=>
        item.id === product.id
        ? {...ProductExist, quantity: ProductExist.quantity   1}
        : item
        )
      );
    } else {
      setCartItems([...cartItems, {...product, quantity: 1}]);
    }
    
  };

  ...

  // Here I am passing the handleAddProduct function as a prop to the 'Inicio.jsx' component
  <Route path='/' exact element={<Inicio handleAddProduct={handleAddProduct} />}/>

Inicio.jsx

Here I am importing the handleAddProduct function as a prop to the 'Inicio.jsx' component and then passing it back as a prop to the Cards.jsx component

const Inicio = ({ handleAddProduct }) => {
  return (
    <>
      <section className="new__product__section">
        <h2 className="title__section__card">Nuevos Productos</h2>
        <Card items={CardItemsHero} handleAddProduct={handleAddProduct} />
        <div className="btn__link__container">
          <Button color="primary" variant="contained" size="large">
            <Link to={'/catalogo'}>
              Ver Catálogo
            </Link>
          </Button>
        </div>
      </section>

    ...

Card.jsx

HERE IS THE PROBLEM 1

const Card = (props, { handleAddProduct }) => {
  return (
    <>
      <div className='card__section'>
        {props.items.map(item => {
          return(
            <div className="product__card" key={item.id}>
              <div className="product__tumb">
                <img src={require('../../assets/'   item.image   '.png')} alt={item.title} />
              </div>
              <div className="product__details">
                <span className="product__category">{item.type}</span>
                <h3>{item.title}</h3>
                <div className="product__bottom__details">
                  <div className="product__price">{'$ '   item.price   '.00'}</div>
                  <div className="product__links">
                    <Link to={'/'   item.id}><InfoIcon /></Link>
                    <span onClick={()=>handleAddProduct(item)}>
                      <ShoppingCartIcon/>
                    </span>
                  </div>
                </div>
              </div>
            </div>
          )
        })}
      </div>
    </>
  )
}

CLARIFICATIONS: the page works perfectly. I am passing the same function in the same way to other components within another component, even with the same <span> line, and the products are added without any problem. I think it's an error when importing the props in Card.jsx but I can't think of what it could be because if I just put {props, handleAddProducts} the page stops working

Here is the repo: https://github.com/LuksFay/Fabianesi-page

CodePudding user response:

The issue is with the Card component. React components receive only a single argument, the props object. In the code the Card component is attempting to destructure handleAddProduct from an undefined argument.

const Card = (props, {handleAddProduct}) => {

Destructure handleAddProduct from the first argument, the props object.

Example:

const Card = ({ handleAddProduct, items }) => { // <-- destructure all from props
  return (
    <>
      <div className="card__section">
        {items.map((item) => {
          return (
            <div className="product__card" key={item.id}>
              <div className="product__tumb">
                <img
                  src={require("../../assets/"   item.image   ".png")}
                  alt={item.title}
                />
              </div>
              <div className="product__details">
                <span className="product__category">{item.type}</span>
                <h3>{item.title}</h3>
                <div className="product__bottom__details">
                  <div className="product__price">
                    {"$ "   item.price   ".00"}
                  </div>
                  <div className="product__links">
                    <Link to={"/"   item.id}>
                      <InfoIcon />
                    </Link>
                    <span
                      onClick={() => {
                        handleAddProduct(item);
                      }}
                    >
                      <ShoppingCartIcon />
                    </span>
                  </div>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

CodePudding user response:

Your Card.jsx file props declaration is not seems to be correct. Change this like bellow.

const Card = (props) => {

  const { handleAddProduct } =  props

  return (
    <>
       [...your code]
    </>
  )
}

Just catch only props and declare the function on the next line like this. You cannot catch props and another value inside props together. you can also declare another props items like the same

const { handleAddProduct, items } =  props

You can directly use the state [items] and function [handleAddProduct] on your jsx inside Card.jsx

CodePudding user response:

Just Update this Card.jsx file: Now Working

you just take only one Concept: props or {items,handleAddProduct}

const Card = (props) => {
  return (
    <>
      <div className="card__section">
        {props.items.map((item) => {
          return (
            <div className="product__card" key={item.id}>
              <div className="product__tumb">
                <img
                  src={require('../../assets/'   item.image   '.png')}
                  alt={item.title}
                />
              </div>
              <div className="product__details">
                <span className="product__category">{item.type}</span>
                <h3>{item.title}</h3>
                <div className="product__bottom__details">
                  <div className="product__price">
                    {'$ '   item.price   '.00'}
                  </div>
                  <div className="product__links">
                    <Link to={'/'   item.id}>
                      <InfoIcon />
                    </Link>
                    <span
                      onClick={() => {
                        props.handleAddProduct(item);
                      }}
                    >
                      <ShoppingCartIcon />
                    </span>
                  </div>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};
  • Related