zustand/docs/guides/updating-nested-state-object-values.md
Jacob Bergholtz 4ed81bc11b
Add usage with context to docs (#1291)
* docs: context guide proposal

* fix(docs): typo & omit comment

* fix(docs): remove horizontal rules

* fix(docs): add wiki link to DI

* fix(docs): format with prettier

* fix(docs): cases that model => where... is needed

* fix(docs): use sentence case

* fix(docs): omit quote block

* fix(docs): into "a" custom hook

* fix(docs): format with prettier

* fix(docs): sort broken nav indexes

* Update docs/guides/initialize-state-with-props.md

Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>

* fix(docs): reintroduce React.createContext example

* scripts: escape quotes

* styles: run prettier

* fix(docs): omit 'React' from imports

* styles: run prettier

* styles: run prettier

Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>
2022-09-18 09:01:06 +09:00

80 lines
1.7 KiB
Markdown

---
title: Updating nested state object values
nav: 3
---
## Deeply nested object
If you have a deep state object like this:
```ts
type State = {
deep: {
nested: {
obj: { count: number }
}
}
}
```
It requires some effort to update the count value immutably.
## Normal approach
The normal approach is to copy state object with the spread operator `...` like so:
```ts
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!
## With immer
Many people use [immer](https://github.com/immerjs/immer) to update nested values. You can use immer to shorten your state updates for deeply nested object like this:
```ts
immerInc: () =>
set(produce((state: State) => { ++state.deep.nested.obj.count })),
```
What a reduction!. [Please take note of the gotchas listed here](../integrations/updating-draft-states.md).
## With optics-ts
There is another option with [optics-ts](https://github.com/akheron/optics-ts/):
```ts
opticsInc: () =>
set(O.modify(O.optic<State>().path("deep.nested.obj.count"))((c) => c + 1)),
```
Unlike immer, optics-ts doesn't use proxies or mutation syntax.
## With ramda
You can also use [ramda](https://ramdajs.com/):
```ts
ramdaInc: () =>
set(R.over(R.lensPath(["deep", "nested", "obj", "count"]), (c) => c + 1)),
```
Both ramda and optics-ts also work with types.
## CodeSandbox Demo
https://codesandbox.io/s/zustand-normal-immer-optics-ramda-updating-ynn3o?file=/src/App.tsx