Reputation: 67
{
"user":{
"auth":true,
"sub_sq":[
"1":{
"createdAt":"2021-08-28"
}
]
},
"sub":{
"name":"123"
"sub_sq":[
"1":{
"createdAt":"2021-08-21"
}
]
}
}
Hello When changing the state object like above
When applying changes to a user object
Do I need to change the entire object after deep copying?
Or do you only apply changes after deepcopy to the user object?
I like the two(2) method, so I'm applying the first (deepcopy only changed object)
but I'm not sure if that's the right way to do it, so I'm asking for advice.
Thank you
Upvotes: 1
Views: 138
Reputation: 5148
In short, you should only copy the stuff you don't change in your new state value. For example:
const newState = {
...oldState,
user: {
...oldState.user,
auth: false,
}
}
More generally, it's considered a better practice to split a deeply nested state object into multiple states. That allows you to be more specific in your state updates and later in your state listeners (i.e. useEffect
). For example, you could split your original state value into two variables:
const [user, setUser] = useState({
"auth": true,
"sub_sq": [
"1": {
"createdAt":"2021-08-28"
}
]
});
const [sub, setSub] = useState({
"name": "123"
"sub_sq": [
"1": {
"createdAt":"2021-08-21"
}
]
});
If you insist on using a composite state, it's better to use a reducer to update each state "part" in a more controlled fashion. From React's useReducer
documentation:
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one
Upvotes: 2
Reputation: 748
Indeed this is a nagging problem with state management. Using the spread operator or the suggested immer
library is a good option. I myself have created the @rimbu/deep
library for this. It has a method named patch
that allows you to write things like:
import { patch } from '@rimbu/deep';
const person = {
name: "Alice",
age: 34,
address: {
street: "Random street",
number: 45
},
friends: ["Bob", "Carol"]
};
const updatedPerson = patch(person)({
age: v => v + 1,
address: {
street: "Other street"
},
friends: v => [...v, "Anne"]
})
// updatedPerson is now:
// {
// name: "Alice",
// age: 35,
// address: {
// street: "Other street",
// number: 45
// },
// friends: ["Bob", "Carol", "Anne"]
// }
It's quite new and needs more documentation, but just wanted to share.
You can play around with this CodeSandbox:
Upvotes: 0