简体   繁体   中英

ReactJS, function only working after two clicks

I know this is a common issue due to asynchronous nature of react hook updates, and I saw there are a few similar questions already. However I can't figure out how to make this work.

I have an empty array of objects (a shopping cart) that, when addToCart is clicked on a specific product, needs to create a new object with all the data about that product. The first time I click, I only get an empty object. From the second time everything seems to work.

Array:

 const [cartArray, setCartArray] = useState([
    { imgUrl: "", nameUrl: "", priceUrl: "", id: "" },
  ]);

Then it's passed as a prop here, where there is the addToCart function and the click events that triggers it:

const Product = ({
  imgUrl,
  nameUrl,
  priceUrl,
  id,
  description,
  cartArray,
  setCartArray,
  productArray,
}) => {
  const [title, setTitle] = useState("");
  const [productId, setProductId] = useState("");
  const [price, setPrice] = useState("");
  const [img, setImg] = useState("");
  const [modalClassName, setModalClassName] = useState("hidden");

  const addToCart = () => {
    setCartArray((prev) => [
      {
        imgUrl: imgUrl,
        nameUrl: nameUrl,
        priceUrl: priceUrl,
        id: id,
      },
      ...prev,
    ]);
  };

  return (
    <div className="product">
      <div className="img-container">
        <img src={imgUrl} alt="product image" />
      </div>
      <div className="product-description">
        <p>{nameUrl}</p>
        <h3>€ {priceUrl}</h3>
      </div>
      <div className="button-container">
        <AddShoppingCartIcon
          className="btn btn-add-to-cart"
          onClick={addToCart}
        />
        <FavoriteBorderIcon className="btn btn-favorite" />
      </div>
    </div>
  );
};

And here's where the Product component is rendered:

const ProductContainer = ({
  productArray,
  setProductArray,
  showNavBar,
  cartArray,
  setCartArray,
}) => {
  useEffect(() => {
    axios
      .get("https://fakestoreapi.com/products")
      .then((res) => setProductArray(res.data));

    console.log(productArray);
  }, []);

  return (
    <div className="product-container-parent" id="shop" onScroll={showNavBar}>
      <div className="product-container-header">
        <h1>New Arrivals</h1>
      </div>
      <div className="product-container">
        {productArray.map((e) => {
          return (
            <Product
              imgUrl={e.image}
              nameUrl={e.title}
              priceUrl={e.price}
              id={e.id}
              description={e.description}
              cartArray={cartArray}
              setCartArray={setCartArray}
              productArray={productArray}
            />
          );
        })}
      </div>
    </div>
  );
};

Any ideas? Thank you!

The initial state for cartArray seems to be having an empty obj { imgUrl: "", nameUrl: "", priceUrl: "", id: "" } The addToCart function appends the new object to the cartArray . So you'll get the empty object as the first one rendered. I would suggest to set initial state for cartArray as empty array.

const [cartArray, setCartArray] = useState([]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM