1

Hi i'm new to react js and i was wondering why my component is rendering twice(useeffect runs twice). I tried removing strict mode and it renders only once but even then i don't understand why count is shown as 01 instead of just only 1. if i add the event handler the component breaks and i get that newarray[id][1]-1 is undefined (the function runs even if i don't click - or +)

import React, { useEffect, useState } from "react";
import { useOutletContext } from "react-router-dom";




function ShoppingCart(prop) {

  const [productstobuy, setProducts] = useState([]);
  const [count, setCount] = useState([0])
  console.log(productstobuy)
/*
   const handlePlusMinus = (sign,id) => {
    console.log("i'm in")
     const newarray = [...productstobuy]
     console.log(newarray)
     if (sign === "+") {
       newarray[id][1] = newarray[id][1]+1
     } else if ((newarray[id][1]-1) >= 1) {
      newarray[id][1] = newarray[id][1]+1
     }
     setProducts(newarray);
     
    }
 */



  const allItems = useOutletContext()

  useEffect(() => {
    setCount(count + 1)
    console.log("called")
    let toadd = allItems.filter((elem, index) => { return index === prop.index })
    console.log(toadd);
    let productexsist = productstobuy.filter((elem) => { return elem[0] === toadd })
    console.log(productexsist.length)


    if (!productexsist.length) {
      console.log([(allItems.filter((elem, index) => { return index === prop.index }))[0], 1])
      setProducts(oldArray => [...oldArray, [toadd[0], 1]]);
      console.log(productstobuy)

    } else {
      console.log("wrong")
    }

  }, [prop.index])







  return (
    <div>
      {count}
      {console.log(productstobuy)}
      {productstobuy.length > 0 ? productstobuy.map((product) => {
        console.log(product[1])
        return (<div className="product" id={prop.index}>{product[0]}<div><button id={prop.index} /*onClick={handlePlusMinus("-",prop.index)}*/>-</button><input type="number" value={product[1]} /><button id={prop.index} /*onClick={handlePlusMinus("-",prop.index)}*/>+</button></div></div>)


      }) : null}
    </div>




  );




}


export { ShoppingCart }



  • 1
    Is your question why your component renders twice or why you're getting `01`? It seems like you already know that it's rendering twice due to strict mode. It looks like your question is mainly only about the `01` issue you're facing and isn't related to thee rendering twice behaviour. The `01` occurs because your state is initially an array `[0]`, which you're adding with `1`, that produces `"01"`. – Nick Parsons Aug 28 '22 at 13:38
  • Yes i was wondering about the 01 issue and also why the component runs handlePlusMinus before rendering the component – NoobWebDesigner Aug 28 '22 at 13:47
  • 1
    The `useEffect` running twice is a default behaviour in `StrictMode` now. https://stackoverflow.com/questions/72238175/react-18-useeffect-is-getting-called-two-times-on-mount – Konrad Aug 28 '22 at 14:07

3 Answers3

2

why count is shown as 01 instead of just only 1

It's because of this line const [count, setCount] = useState([0]). count should be initialised as a number instead of an array. What actually happened in the useEffect was setCount([0]+1) instead of the intended setCount(0+1)

the function runs even if i don't click - or +

Instead of putting onClick={handlePlusMinus("-",prop.index)}, try onClick={() => handlePlusMinus("-",prop.index)}instead. this would ensure that the handlePlusMinus function is only called when the element is clicked. Elaboration here: React onClick function fires on render

1

It renders twice because of the Strict Mode.
https://reactjs.org/docs/strict-mode.html

szgezu
  • 68
  • 4
1

I am assuming you are using react 18 latest. so in develop mode it executes useEffect twice.

You can just remove <Strict> </Strict>

In App.js it should work as expected

Keep in mind Strict component gives a lot of useful warnings.

nima
  • 7,796
  • 12
  • 36
  • 53