Update nested properties in a State object in React

avatar

Borislav Hadzhiev

Wed Apr 27 20222 min read

Update nested properties in a State object in React #

To update nested properties in a state object in React:

  1. Pass a function to setState to get access to the current state object.
  2. Use the spread syntax (...) to create a shallow copy of the object and the nested properties.
  3. Override the properties you need to update.
App.js
import {useState} from 'react'; export default function App() { const initialState = { name: 'Alice', address: { country: 'Austria', coords: [1, 2], }, }; const [employee, setEmployee] = useState(initialState); const updateNestedProps = () => { setEmployee(current => { // 👇️ using spread syntax (...) return { ...current, address: { ...current.address, // 👇️ override value for nested country property country: 'Germany', }, }; }); }; return ( <div> <button onClick={updateNestedProps}>Click</button> <h4>{JSON.stringify(employee, null, 4)}</h4> </div> ); }

update nested state property

We used the spread syntax (...) to unpack the key-value pairs of the objects into a new object creating shallow copies.

App.js
const employee = { name: 'Alice', address: { country: 'Austria', coords: [1, 2], }, }; const newEmployee = { ...employee, address: { ...employee.address, // 👇️ override country property country: 'Germany', }, }; // 👇️ newEmployee.address.country is 'Germany' now console.log(newEmployee);

Notice that we aren't directly mutating the state object in any way.

We are unpacking the key-value pairs of the state object into a new object and overriding the properties we want to update.

The country property overrides the property with the same name that exists on the object because we provided it after using the spread syntax.

We passed a function to setState, because the function is guaranteed to be invoked with the current (most up to date) state.

App.js
const updateNestedProps = () => { setEmployee(current => { // 👇️ using spread syntax (...) return { ...current, address: { ...current.address, // 👇️ override value for nested country property country: 'Germany', }, }; }); };

When the next state is computed using the previous state, pass a function to setState.

Otherwise, we might get some weird race condition if the state object we have access to does not represent the most up to date value.

Alternatively, you can create a copy of the nested object and directly update the property on the copy.

App.js
import {useState} from 'react'; export default function App() { const initialState = { name: 'Alice', address: { country: 'Austria', coords: [1, 2], }, }; const [employee, setEmployee] = useState(initialState); const updateNestedProps = () => { setEmployee(current => { // 👇️ get copy of nested object const address = {...current.address}; address.country = 'Germany'; return {...current, address}; }); }; return ( <div> <button onClick={updateNestedProps}>Click</button> <h4>{JSON.stringify(employee, null, 4)}</h4> </div> ); }

This example achieves the same result, however is a bit more difficult to read and a bit more tricky.

We created a copy of the state.address object and directly updated the country property on the copy.

Then we set the address property in the new state object to the copy we updated.

Which approach you pick is a matter of personal preference. I'd go with the first example because it is much more intuitive to simply override the properties we want to update.

Use the search field on my Home Page to filter through my more than 1,000 articles.