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

why my forEach and useState change the first object when it ran the second time

i have a simple cart logic with use state i want to update object inside of array whos name is surya and because react strick mode print 2 times the first value was right but the second value make change to arr[0]

is there something i miss

const [coba, setCoba] = useState([
    { name: "aditya" },
    { name: "joni" },
    { name: "surya", money: 2000 },
  ]);

  coba.forEach((item) => {
    let arr = [];
    if (item.nama === "surya") {
      item.money = 500000;
      arr.push(item);
      setCoba((prev) => {
        return [
          {
            ...prev,
            ...arr,
          },
        ];
      });
    }
  });
  console.log(coba);

it console like this

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

[
  { name: 'aditya' },
  { name: 'joni' },
  { name: 'surya', money: 500000 }
]

    [
  {
    '0': { name: 'surya', money: 500000 },
    '1': { name: 'joni' },
    '2': { name: 'surya', money: 500000 } 
  }
]

i want to know why the second time it run its change the value of arr[0]object whos name: aditya

>Solution :

The behavior you observe is du to several mistakes:

Array manipulation:

  • You have a prev array with three items: [0, 1, 2]
  • You create a new array with only one item [0]
  • You merge them inside an object, so the index from the arrays are gettings used as keys, since the new array comes second, its element at index 0 will erase the element at index 0 in prev. This is why surya is logged as the first item in the resulting array.

State manipulation:
You are modifying an element of the array in the state. Since object are manipulating by reference, you are updating the object at all places. This is why the third row gets modified too.
In addition you should never call ‘useState’ inside the rendering pat of a component or inside a loop (as pointed out in comments) or you might end with infinite rendering loops.

Here is a sample code pen doing what you want with a click handler (you can use useEfect if you prefer this to be done initially): https://codepen.io/aSH-uncover/pen/WNLOOdK

  // Hooks //
  
  const [coba, setCoba] = useState([
    { name: "aditya" },
    { name: "joni" },
    { name: "surya", money: 2000 },
  ]);
  
  // Event Handlers //
  
  const handleClick = () => {
    setCoba((prev) => {
      const surya = prev.find(c => c.name === 'surya')
      surya.money += 1000
      return [...prev];
    });
  }
  
  // Rendering //
  
  return (
    <div>
      {coba.map(c => <div>{c.name} {c.money}</div>)}    
      <button onClick={handleClick}>Give Money to Surya</button>    
    </div>
  )
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