0

I have a pretty large object named cardRouteData (simplified in this example) and an array of integers named comulatedTimeOnSpotArr. I am trying to change the attribute value of "duration-with-stops" whenever comulatedTimeOnSpotArr changes.

const [comulatedTimeOnSpotArr,setComulatedTimeOnSpotArr] = useState([0,3600,20000])
const [cardRouteData,setCardRouteData] = useState({"duration":11450, "duration-with-stops":31145})

useEffect(() => {
        if( comulatedTimeOnSpotArr!== undefined && comulatedTimeOnSpotArr.length >0){
            let tempCardRootData = cardRouteData
            tempCardRootData['duration-with-stops'] = cardRouteData.duration + comulatedTimeOnSpotArr[comulatedTimeOnSpotArr.length -1]
            setCardRouteData(tempCardRootData)
        }
    }, [comulatedTimeOnSpotArr])



useEffect(() => {
        if( cardRouteData!== undefined){
            console.log('cardRouteData has changed')
        }
    }, [cardRouteData])

Now lets say I have an onClick function in my html that changes the last value of "comulatedTimeOnSpotArr" such as [0,3600,4000] Then useEffect should trigger and set the new value of "duration-with-stops" in "cardRouteData" to 15450. For some reason, it is not setting the new value, and it does not log the 'cardRouteData has changed' message to the console.

JK2018
  • 429
  • 1
  • 9
  • 23
  • `let tempCardRootData = cardRouteData` makes no effect. It just creates a new reference to the **same** object in memory. You need to copy it `const tempCardRootData = { ...cardRouteData}` <-- creates a shallow copy – Yury Tarabanko Mar 01 '23 at 17:18
  • 1
    Does this answer your question? [Updating an object with setState in React](https://stackoverflow.com/questions/43638938/updating-an-object-with-setstate-in-react) – Yury Tarabanko Mar 01 '23 at 17:21

1 Answers1

1

The assignment let tempCardRootData = cardRouteData makes a copy of a pointer, not a copy of the object. The referential identity is still the same.

Make sure you make a copy with a new identity, and not mutate the old object:

let tempCardRootData = { ...cardRouteData } // copy object, not reference
tempCardRootData['duration-with-stops'] = cardRouteData.duration + comulatedTimeOnSpotArr[comulatedTimeOnSpotArr.length -1]
setCardRouteData(tempCardRootData)

When calling set state, there is a check for verify whether the object has changed by simple equality:

setState(newValue) {
   if (newValue !== oldValue) scheduleNextRender();
   // ...
}
Slava Knyazev
  • 5,377
  • 1
  • 22
  • 43