Why isn't my React component updating (using Redux)?

Why oh why doesn’t that React component update?

You have done everything right! You know that.

You have written Action creators and reducers. You have connected the store to the component, passing in props properly. And you call the action from the component.

And still, nothing happens…

There are many reasons why things could have gone wrong here. But the most common reason is that you mutate the state in your reducers.

You should never mutate state in your reducers.

But what does mutate state mean?

And why can it cause bugs?

And maybe most importantly… what should you do?

Immutable and mutable data

First, a quick reminder what is mutable and immutable data.

  • Immutable data is data that cannot be changed once it has been created.

  • Mutable data is data that can be changed once it has been created.

JavaScript does not have immutable data structures built in, but we can act as if we did. Instead of changing an object directly, we can clone it and add changes to the cloned object with Object.assign or the spread operator.

Pass by reference

Before we move on, we need to learn about objects in JavaScript.

When we assign an object to a variable, what we really do is assign a reference to that object. Look at this example:

const a = {}

const b = a

Now, a and b points to the same object.

If we mutate b, we also mutate a because they point at the same object.

a.a = "a"

console.log(b) // outputs {a: "a"} even though we haven't changed b

We can see that they are the same by doing a ===

console.log(a === b) //outputs true

If we do an Object.assign, we see that the new object we get has a new reference:

const c = Object.assign({}, a)

console.log(a === c) //outputs false

Why does the reducer require immutable data?

Ok, now we are ready to learn why Redux operates with immutable data only!

When an action has been dispatched, Redux checks if the state has changed or not. If it has not changed then it doesn’t have to update the components.

Redux checks if the state has changed by checking if the reference to the state object has changed. It looks something like this:

const hasChanged = oldState !== newState

If you mutate the data then the reference will be the same - even though the data is changed - and Redux will not see that the state has changed. When Redux cannot see that the state has changed, it will not update the React components with new data from the state.

How to avoid bugs with immutable data

The way to “tell” Redux that the state has changed is to create a new object - which will have a new reference. We do that by cloning the old state, and adding our changes on top of the new object.

const newState = Object.assign({}, oldState, { modalOpen: true })

You can do the same with less syntax:

const newState = { ...oldState, modalOpen: true }

The ... is the ES6 spread syntax

What syntax you use is entirely up to you!

Avoid bugs by understanding Redux deeply

The best (but not the quickest) way to avoid bugs and bad code is to develop a _deep understanding_of the technology you are working with.

When I was learning Redux I was surprised when I realized that the source code for Redux is totally understandable - even for a beginner. I decided to code a mini version of Redux and it was only 18 lines of code.

Get one step closer to master Redux - get my free ebook by signing up below!