In my React app I purposely combined several arrays in one state using a useState hook. These arrays represent visual objects that I would like to keep "managed" together to ensure that that re-renderings of my application are visually consistent.
While testing I tried to change a property of some objects of my first array. updatedElements
reflects the update properly (clearly shown by my console-log). However, updating my useState state does not work. The array elements
does not change at all.
Here is the relevant code:
const updatedElements: VisualDiagramElementData[] =
visualData.elements.map((element: VisualDiagramElementData) =>
element.id === id
? { ...element, selected: true }
: { ...element, selected: false }
);
console.log(updatedElements);
setVisualData({
elements: updatedElements,
connectors: visualData.connections,
connections: visualData.connections,
});
What am I missing / doing wrong? Any help is highly appreciated!
CodePudding user response:
When updating a state property based on its previous value, the callback argument of the state setter should be used. Otherwise you may use stale state values.
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
https://reactjs.org/docs/hooks-reference.html#functional-updates
It should be:
setVisualData((visualData)=>({
elements: visualData.elements.map(/*Your map callback*/),
connectors: visualData.connections,
connections: visualData.connections,
}));
CodePudding user response:
I would go with what is recommended in the React docs - split them out into multiple state variables: https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables.
Depending on how you trigger the state updates will determine whether re-render occurs multiple times or not. See this answer for more details on how the batching works: https://stackoverflow.com/a/53048903/6854709
Also take note of the comment by aprillion:
Note from github.com/facebook/react/issues/10231#issuecomment-316644950 - This is implementation detail and may change in future versions.
CodePudding user response:
Eventually, it worked by using the "callback argument of the state setter". I revised / reviewed my entire code and I modified all my state setters accordingly. Now, everything works like a charm. Thank you very much again for your help, especially to Nice Books.