Let’s say I have a code scenario like this….
const obj = {
dogs: ["terrier", "labrador", "poodle"],
ages: [4,6,11],
names: ["Fido", "Max", "Spot"]
};
const [data, setData] = useState(obj);
Then, I want to change one of the names in the array to Richard, for example. How can I do this efficiently?
What I’ve been doing is cloning the object with let clone = JSON.parse(JSON.stringify(obj))
then modifying the clone, then calling setData(clone)
. I feel like there has got to be a better way though where I don’t have to clone the object.
3
Answers
As pilchard commented you need to do a copy to trigger a change, but you can do with the new deep clone:
If you don’t clone the object React doesn’t know that you have updated state since it is checked by reference equality. That being said the
JSON
approach isn’t great, see What is the most efficient way to deep clone an object in JavaScript? for full discussion.But a deep clone is actually unnecessary in this situation, a shallow copy of the containing object, and a clone of any mutated nested objects is sufficient. Here is an example updating the nested
dogs
array using spread syntax to clone the object andmap()
to update the necessary nested array.My advice would be to split it into 3 state values:
To change a name, you can then clone the
names
collection (instead of the entire object) and update that:To me this makes it much clearer that only a certain part of the state is being updated, and it eliminates the risk of inadvertent changes to other parts of the state.
Also it is more efficient, although for such a small dataset the difference will not be noticeable.