My react state is changing without me calling my setState function from useState hook.
After some quick research, i've narrowed it down to the fact an array is a reference type so data and tempData share the same reference and change with each other. A solution I found was to stringify then parse the data: JSON.parse(JSON.stringify(data)) but this could have some pretty bad performance hits if it's a large object right? Is there a better solution here? Redux? Or is that unnecessary? This is a pretty common case isn't it?
For anyone who cares, this works too but is kinda ugly:
change state to object rather than array
const defaultData = {
  data: [
    {id:0, foo:1, bar:2},
    {id:1, foo:3, bar:4},
    {id:2, foo:4, bar:6},
  ] 
}
const handleData = (id) => {
    setData((prevState) => {
      return {data: data.data.map((i) => i.id === id ? {...i, id:i.id+10} : {...i})}
    })
  }
I've attached an example below which can be easily created from create-react-app.
App.js
import Child from './Child';
import { useState } from 'react';
const defaultData = [
  {id:0, foo:1, bar:2},
  {id:1, foo:3, bar:4},
  {id:2, foo:4, bar:6},
]
function App() {
  const [data, setData] = useState(defaultData)
  const handleData = (id) => {
    const tempData = data
    for (const idx in tempData) {
      const item = tempData[idx]
      if (item.id === id) {
        tempData[idx].id += 10
      }
    }
  }
  return (
    <div>
      <Child data={data} handleData={handleData} />
    </div>
  );
}
export default App;
Child.js
export default function Child(props) {
  const {data, handleData} = props
  
  return (
    <div>
      
      <ul>
      {data.map((i) => (
        <li key={i.id}>
          <button onClick={() => handleData(i.id)}>
            {i.foo} {i.bar}
          </button>
        </li>
      ))}
      </ul>
    </div>
  )
}
