%% generate tags start %%
#software-engineering
%% generate tags end %%
#software-engineering/react
use function setter and create a new object to ensure the state will be update.
```tsx
import { useState } from 'react';
export default function App() {
const [info, setInfo] = useState({
name: 'React',
meta: {
year: 2013,
data: {
developer: 'Meta',
versions: {
latest: [16.0, 17.1, 18.1],
},
},
},
});
// First Method
const addVersion = (newVersion) => {
setInfo((prevInfo) => ({
...prevInfo,
meta: {
...prevInfo.meta,
data: {
...prevInfo.meta.data,
versions: {
latest: [
...prevInfo.meta.data.versions.latest,
newVersion
]
}
}
}
}))
}
// Second Method
const addVersionAlt = (newVersion) => {
setInfo((prevInfo) => {
const newInfo = { ...prevInfo }
newInfo.meta.data.versions.latest.push(newVersion)
return newInfo;
})
}
return (
<div>
<h4>The latest version are: {info.meta.data.versions.latest.join(', ')}</h4>
<button onClick={() => addVersion(18.2)}>
Add Version
</button>
<button onClick={() => addVersionAlt(18.3)}>
Add Version (Alt)
</button>
<pre>{JSON.stringify(info, null, 2)}</pre>
</div>
)
}
```
There are other method documentation in zustand documentation.
[Zustand Documentation (pmnd.rs)](https://docs.pmnd.rs/zustand/guides/updating-state)
## With [[Immer]]
Many people use [Immer](https://github.com/immerjs/immer) to update nested values. Immer can be used anytime you need to update nested state such as in React, Redux and of course, Zustand!
You can use Immer to shorten your state updates for deeply nested object. Let's take a look at an example:
```ts
immerInc: () =>
set(produce((state: State) => { ++state.deep.nested.obj.count })),
```
What a reduction! Please take note of the [gotchas listed here](https://docs.pmnd.rs/zustand/integrations/immer-middleware).
## 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)),
```
## with [[mutative]]