Explain Codes LogoExplain Codes Logo

How to update nested state properties in React

javascript
react
immutability
state-management
Anton ShumikhinbyAnton ShumikhinΒ·Oct 3, 2024
⚑TLDR

In React, the mutable objects can be updated seamlessly using spread syntax (...).

this.state = { user: { name: "Alice", details: { age: 30 } } };

To increment the age without modifying the rest:

this.setState(prevState => ({ user: { ...prevState.user, details: { ...prevState.user.details, age: prevState.user.details.age + 1 } // It's Alice's birthday today! 🎈 } }));

This method allows you to safely alter nested properties without affecting unrelated parts of the state, in line with React's immutability principle.

Handling complexity using Immutability-helper

With complex nested state, using only spread syntax can make things tricky. Immutability-helper is your best friend in such situations.

import update from 'immutability-helper'; this.setState(prevState => update(prevState, { user: { details: { age: {$set: prevState.user.details.age + 1} // Alice is a time traveler, age is just a number! } } }));

It simplifies your code, making modifications on nested state easier to understand, and opens up more powerful operations over immutability.

Avoiding re-renders: A note on performance

Nested state updates can cause unwanted re-renders due to React's shallow comparison in shouldComponentUpdate(). This could hamper performance. To mitigate this, consider simplifying your state or using MobX with observables for better state management.

Mutating state: A cardinal sin

Mutating state directly in React is bad and can lead to unexpected behaviour. Always use setState or the hooks counterpart useState to update your state:

const [user, setUser] = useState({ name: 'Alice', details: { age: 30 } }); // Update nested state const updateUserAge = () => { setUser(user => ({ ...user, details: { ...user.details, age: user.details.age + 1 } // Winter is coming, and so is Alice's birthday! β„οΈπŸŽˆ })); };

Effective strategies for state updates

Reconsider your components

Structure your components according to your state updates. If you find yourself contemplating nested state updates frequently, try simplifying your state or create more granular components.

Flat props to the rescue

Pass flat props to child components whenever possible. This simplifies things and makes clear the component's dependencies.

Complexities of nested updates

Dealing with lists or arrays in state objects demands careful handling to avoid unexpected mutations. Make sure to spread or .map() elements correctly.

Enhanced methods for simplifying your life

When Object.assign comes calling

Object.assign is an alternative way to handle nested state updates:

this.setState(prevState => ({ user: Object.assign({}, prevState.user, { details: Object.assign({}, prevState.user.details, { age: prevState.user.details.age + 1 }) }) // Object.assign to the rescue! πŸ¦Έβ€β™€οΈ }));

New objects ensure the state's immutability remains intact.

Sequential updates using comma operator

Utilise JavaScript's comma operator to do sequential state updates:

this.setState(prevState => ({ user: { ...prevState.user, name: 'Bob' }, // Bob who? Alice just got a makeover! πŸ’„ }), () => this.setState(prevState => ({ user: { ...prevState.user, details: { ...prevState.user.details, age: 25 } } // Bob's been hitting the gym hard! πŸ’ͺ })));

Avoid traps in shouldComponentUpdate()

Ensure that shouldComponentUpdate() does not get too complex if you want to manage a large nested state effectively. This could otherwise lead to performance issues .