%% 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]]