-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Updating nested state object values
Daishi Kato edited this page Jan 5, 2022
·
7 revisions
If you have a deep state object like this:
type State = {
deep: {
nested: {
obj: { count: number }
}
}
}
It's requires some effort to update the count value immutably.
The normal approach is to copy state object with ...
:
normalInc: () =>
set((state) => ({
deep: {
...state.deep,
nested: {
...state.deep.nested,
obj: {
...state.deep.nested.obj,
count: state.deep.nested.obj.count + 1
}
}
}
})),
This is very long!
Many people use immer to update nested values:
immerInc: () =>
set(produce((state: State) => { ++state.deep.nested.obj.count })),
What a reduction!
There's another option with optics-ts:
opticsInc: () =>
set(O.modify(O.optic<State>().path("deep.nested.obj.count"))((c) => c + 1)),
Unlike immer, optics-ts doesn't use proxies nor mutation syntax.
You can also use ramda:
ramdaInc: () =>
set(R.over(R.lensPath(["deep", "nested", "obj", "count"]), (c) => c + 1)),
This works with types as well as optics-ts.
https://codesandbox.io/s/zustand-normal-immer-optics-ramda-updating-ynn3o?file=/src/App.tsx