During my time as a React developer, I have experienced that you never should mutate your state, as it leads to weird bugs when rendering your components. This article will show you some tricks on how to make your state immutable, achieving a more bug-free UI.
Your state and values should be immutable, always. This means that you should not modify the state, but rather make a copy of it and then add or remove data. This is because React depends on knowing if some state or props have changed to be able to decide if the component needs to re-render. React compares the previous value with the potentially updated value. If previous value is mutated, it will not re-render properly because React may not detect the changes.
Take a look at the different ways to avoid mutating your values.
Immutable variables
Historically, JavaScript developers commonly used let
or var
when creating variables. When ES6 came, it introduced the const
keyword which was a new way to create a variable. By using const
you cannot change the value of the variable after it has been created. Consistently using const
enforces you to make a copy of the variable when creating a new value.
// ❌ Will give you an error
const myVariable = 1
myVariable = 2
// ✅ Will work
const myVariable = 1
const myOtherVariable = 2
Immutable arrays
Updating arrays is common to do in React, and if you are experienced with JavaScript it may familiar to use the .push
array function. By using the .push
method you are mutating your list, which is unfortunate. Make a copy instead and add the desired value:
const myList = [1, 2, 3, 4]
// ❌ Dont mutate the list
myList.push(5)
// ✅ Adding values to the list
const newList = [...myList, 5]
If you want to modify, filter or remove values in your array, you can use the .map
, .filter
or .reduce
array functions. These functions loop through the array and creates a new list, and they don't mutate the original list. Take a look at an example with .map
.
const myList = [
{ value: 1 },
{ value: 2 },
{ value: 3 },
{ value: 4 }
]
const myOtherList = myList.map(({ value }) => {
return value * 2
})
// [{ value: 2} { value: 4 } { value: 6 } { value: 8 }]
Immutable objects
It is also not recommended to mutate objects as well. You should always make a copy by spreading the values from the object and then modify the values as you want.
const myObject = {
a: 1,
b: 2,
}
// ❌ Don't mutate the object
const myObject.c = 3
// ✅ Make a copy and then change the value
const newObject = {
...myObject,
c: 3
}
Please don't use lodash
While Lodash provides various methods for handling lists or objects, such as sorting, grouping, or checking for equality, it's not the most optimal solution. Lodash consumes a significant amount of space and, more importantly, it mutates your data. Some lovely developers have created this great Github project named You might not need lodash, giving you an overview of how to make similar functions you can add directly to your code without downloading a third-party library. This is great since they give you functions that are immutable, and you are getting a deeper understanding of how the code actually works.
(They also created an eslint-rule you can add to your project if you are using lodash, giving you a warning where you use functions from lodash that can be replaced).
Hope you learned something about immutability!