Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Counter incrementing by 2 rather than 1

Currently trying to useState with prevState for incrementing and decrementing my counter but it is
\ incrementing and decremeting by 2 each time, even though I only want it to do it once each time.

I’ve tried to return updatedProducts[index].count however it returns an error that products.map is not a function, I assume because I am no longer passing in an array.

  const [product, setProduct] = useState([])

  const decrementCount = (index) => {
    setProduct((prevState) => {
      const updatedProducts = [...prevState];
      // create min for the count, can not go less than 0
      // math.max() returns the value that is the smallest
      const newCountdown = Math.max(0, updatedProducts[index].count - 1)
      updatedProducts[index].count = newCountdown;
      return updatedProducts
    });
  }

  const incrementCount = (index) => {
    setProduct((prevState) => {
      // const updatedProducts = [...prevState];
      const updatedProducts = [...prevState];
      // create max for the count, can not go more than 10
      const newCount = Math.min(10, updatedProducts[index].count + 1)
      updatedProducts[index].count = newCount;
      // console.log('This is the count'+updatedProducts[index].count)
      return updatedProducts;
    });
  }

  const url = 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline'

  async function callAPI() {
    try {
      const request = await fetch(url);
      if (request.status === 200) {
        console.log('Success!');
        const response = await request.json();
        // this spreads the items from the response call and adds a count of 1 to each card/image
        const productsWithCount = response.map((item) => ({
          ...item, count: 1

        }));
        setProduct(productsWithCount);
      } else {
        console.log(`Server error: ${request.status}`);
      }
    } catch (err) {
      console.log(`Fetch error: ${err}`);
    }
  }

  return (
    <div>
      <input
        type="text"
        placeholder="Search here" />

      <button onClick={callAPI}>Click to get API</button>
      <div className='shopCards grid grid-cols-5'>
        {
          product.map((item, index) => {
            return (
              <div key={item.id}>
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
                </svg>
                <img src={item.api_featured_image} ></img>
                <div className='addToCart'>
                  <div className='productQuantity'>
                    <button onClick={() => incrementCount(index)} value={item.id}>
                      +
                    </button>
                    <p>{item.count}</p>
                    <button onClick={() => decrementCount(index)}>
                      -
                    </button>
                  </div>
                  <button>
                    Add to cart
                  </button>
                </div>
              </div>
            )
          }

          )
        }

      </div>
    </div >
  )
}

export default Shop

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

const updatedProducts = [...prevState]; is a shallow copy, and doesn’t copy the objects within the array. React state should be immutable, but the line updatedProducts[index].count = newCountdown; mutates prevState.

Try

const updatedProducts = prevState.map(e => ({...e}));

which copies each object within the array as well as the array. It’s then safe to use = to mutate the copy.

If your objects have nested objects or arrays, you’ll want to copy those, too, as the above code only performs a shallow copy of each object.

Also, <StrictMode> can cause double renders, so check that that’s not interfering.

Naming nitpick: I’d use [products, setProducts] because it’s an array of multiple products.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading