AccueilClientsExpertisesBlogOpen SourceContact

1 octobre 2024

Why Mutating State is Problematic in React

3 minutes de lecture

Why Mutating State is Problematic in React
🇫🇷 This post is also available in french

When I conduct React training sessions, one recurring issue participants face is state mutation. It's often a subtle problem, and to fully grasp it, you need to understand how React manages state.

This article aims to clarify why mutating state is problematic in React and how to effectively avoid it.

The Problem

Let's consider a simple example. You have an array in the state that you want to update:

const [items, setItems] = useState([1, 2, 3])

const addItem = () => {
  items.push(4)
  setItems(items) // Oops, we're mutating the array here
}

When you run this function, you might expect the component to update with the added item. But no, nothing happens. Why? Because the reference of the items array hasn't changed. You only modified its content, and React doesn't detect that.

The result: no UI update. What we have done here is a state mutation.

Understanding Mutation

Imagine your application as a residential neighborhood filled with houses, where each variable is a house with its own postal address. When you create a variable, you assign it an address.

Array

Mutating an object is like renovating the interior of a house without changing its address. You can repaint the walls, add furniture, but the address stays the same.

Array

React, on the other hand, doesn't look inside the houses. It only cares whether the address has changed. If the address remains the same, React assumes there is no change and doesn't trigger an update. This is where mutating state becomes problematic: you're altering the inside of the object, but React has no idea and continues to rely on the old version of the UI.

Undesirable Effects

The problem can also occur in hooks like useEffect, where mutating the state can prevent side effects from running. A classic example:

user.username = 'Romy'

useEffect(() => {
  console.log('user has changed!')
}, [user])

If you mutate the user object instead of creating a new reference, the effect will never be called. This bug doesn't generate visible errors but results in unexpected behaviors that can accumulate.

The Solution: Copy, Don't Mutate

So how do we avoid this problem? The solution is simple: instead of mutating your objects or arrays, create new copies using operators like the spread operator (...) or methods like concat. Here's how to fix our previous example:

const addItem = () => {
  const newItems = [...items, 4] // New reference
  setItems(newItems) // State update
}

Here, we're creating a new array, which generates a new reference. React detects this change, and the UI updates correctly.


Array

Similarly, for objects:

const updateUser = () => {
  const newUser = { ...user, age: 30 } // New reference
  setUser(newUser)
}

Note that for simple variables known as atomic (string, number, boolean...), we don't have this mutation problem.

These data types are immutable by nature in JavaScript. When you "modify" a variable of this type, you're actually creating a new value with a new reference. This is why React can easily detect changes on these data types.

Why This Matters

React relies on reference comparison to optimize UI updates. Instead of performing a deep comparison (which would be performance-intensive), it simply checks if a new reference has been created. If it has, React knows it needs to reconcile the DOM with the new state.

This optimization is crucial for maintaining acceptable performance, especially in complex applications. Comparing every property of an object or every element of an array on every state change would significantly slow down rendering. By creating a new reference, you ensure a smooth and predictable update process.

In Summary

Mutating state is like redecorating a house without changing the address: no one notices the changes. Creating a new reference, however, allows React to do its job and update the UI.

So, next time you're managing state, remember: don't mutate, duplicate!

👋🏼

À découvrir également

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

12 Jun 2024

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

Dans ce premier article d’une série consacrée à l’IA et l’UI, je vous propose de découvrir différentes manières d’intégrer ces modèles d’IA dans vos applications React pour améliorer l’expérience utilisateur.

par

Baptiste

Retour d'expérience chez 20 Minutes : s'adapter au journalisme numérique

30 May 2024

Retour d'expérience chez 20 Minutes : s'adapter au journalisme numérique

Dans cet article, vous ne trouverez pas de snippets ou de tips croustillants sur React, seulement le récit d'une aventure plutôt ordinaire à travers le développement et l'évolution d'un projet technique.

par

Vincent

Améliorez vos composants avec Storybook

17 Nov 2020

Améliorez vos composants avec Storybook

Connaissez-vous Storybook ? Cet outil open-source offre un environnement...

par

Baptiste

Premier Octet vous accompagne dans le développement de vos projets avec react

En savoir plusNous contacter
18 avenue Parmentier
75011 Paris
+33 1 43 57 39 11
hello@premieroctet.com

Suivez nos aventures

GitHub
X (Twitter)
Flux RSS

Naviguez à vue