Why we NEVER MUTATE STATE in React Javascript
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.

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.