Why we NEVER MUTATE STATE in React Javascript

Andrew Ogaga
4 min readOct 17, 2020

We have always accepted not to directly mutate the state in React, be it local state within the components or the redux state with regards to reducers. Have you given thought to why that is? This article will try to improve our knowledge on why state mutation is a taboo if you dont want to have buggy code in production.

Why we dont mutate state in react js — Andrew Ogaga

First of all, lets understand some basic concepts regarding Javascript data types.

Primitive Data Types:

There are 5 primitive data types in Javascript which are Strings, Numbers, Booleans, Nulls, and Undefined and these are passed by value when being copied or reassigned. This means that a new space in memory is created for each value being reassigned. See example below.

let a = "obinna";
let b = a;
console.log(a) --> "obinna"
console.log(b) --> "obinna"

It means that a was assigned a memory space and b was also assigned a memory space based on their values and a change in value of a will not affect the value of b. See below for example.

let a = "obinna";
let b = a;
a = "segun";
console.log(a) --> "segun"
console.log(b) --> "obinna"

From illustration above we will notice that a change in a had no effect on b.

Non-primitive data types

Some examples of non-primitive data types are Objects, Functions and Arrays. These types of data are passed by reference and this will be explained below.

let original = {value: "ahmed"}
let copied = original;
console.log(original) --> {value: "ahmed"}
console.log(copied) --> {value: "ahmed"}

If we decide to mutate the object original by changing the value of original.value, we notice that copied.value will also change.

let original = {value: "ahmed"}
let copied = original;
original.value = "moses";
console.log(original) --> {value: "moses"}
console.log(copied) --> {value: "moses"}

This behaviour is seen because of the way in which Javascript saves their non-primitive values to variables. The values to be saved to memory are saved, the address to that location in memory is also saved and finally, all variables are referenced to the address in location.

So in this case where the object original is reassigned to a new variable copied, it does not recreate a new address in memory nor does it create a new object in memory. What it does is to reference the new variable copied to the same object in memory. Hence, a change in any of the variables original or copied will effectively change the value in memory which will be seen by both copied and original. Isnt that interesting?

More details can be found in a very good article by Arnav Aggarwal

So what does this all have to do with immutability in React?

So, React as a JS framework rerenders its components if the props or the state of that component changes. In this article, we will be making use of React hooks to illustrate our example while making use of an object as the the initial state (as seen in the useState below) to correctly illustrate effect of mutating a state.

import React, { useState } from 'react';

function Example() {
const [name, setName] = useState({name: 'Aisha'}});
return (
<div>
<p>You changed the Name to {name.name}</p>
<button onClick={() => setName({name: 'Wale'})}>
Change name
</button>
</div>
);
}

From example above, we notice that the state name changes by making use of setName function produced by the hook useState. Consequently, if the name changes after the button click, the component rerenders to show the new name Wale.

One might be tempted to change the state of name by doing so:

name.name = 'Wale';

Technically, this is one way of changing the property of a Javascript object but in the case of React, this is not advised as the address of the variable name is not changed. It changes the value of name.name in memory but as react does not notice a change in the address of the memory, it does not recognize it as a change. Hence, the component is not rerendered.

If we rerender that component by any other means (correctly changing state or props), its rerender will show that the value has been changed and will display Wale.

This could cause a bug in your codebase and will be very very hard to track so its strongly advised to make use of setState in Class based components and the setter of useState in React hooks.

I will love to see contributions in the comments section on how this article can be improved or any question regarding this so we can learn together.

Thanks Guys.

--

--

Andrew Ogaga

A Software Engineer with a flare for knowledge and a motto “Determination begets Success”.