Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the consequences of mutating state in a reducer?

Tags:

react-redux

The redux guide states:

We don't mutate the state. We create a copy with Object.assign(). Object.assign(state, { visibilityFilter: action.filter }) is also wrong: it will mutate the first argument. You must supply an empty object as the first parameter. You can also enable the object spread operator proposal to write { ...state, ...newState } instead.

I happened to catch myself writing the following snippet of working code:

[actions.setSelection](state, {payload}) {
    state[payload.key] = payload.value;
    return state;
},

I had a bad vibe about it, and revisited the guide for wisdom. I have since rewritten it as this:

[actions.setSelection](state, {payload}) {
    const result = Object.assign({}, state);
    result[payload.key] = payload.value;
    return result;
},

I am fairly sure I have offended the commandment noted above elsewhere in my code. What kind of consequence am I looking at for not tracking them down with diligence?

(Note: The reducer syntax above is via redux-actions. It would otherwise be the block of code in a reducer fn switch/case.)

like image 438
Chris Lincoln Avatar asked Feb 15 '18 12:02

Chris Lincoln


People also ask

Can Redux reducers mutate the original state?

In Redux, our reducers are never allowed to mutate the original / current state values! // ❌ Illegal - by default, this will mutate the state! There are several reasons why you must not mutate state in Redux: It causes bugs, such as the UI not updating properly to show the latest values

Why do reducers have different state parameters for each component?

Note that each of these reducers is managing its own part of the global state. The state parameter is different for every reducer, and corresponds to the part of the state it manages. This allows us to split up our logic based on features and slices of state, to keep things maintainable.

Is mutating state in react an anti-pattern?

"Mutating state in React is an anti-pattern". Most of us who use React know this and grudging accept this. But there are serious consequence to not making your React/Redux code immutable. A codebase that I was working on had a weird bug. The component I was making relied on a redux state object.

How do you write a reducer?

Now that we know what our state structure and our actions look like, it's time to write our first reducer. Reducers are functions that take the current state and an action as arguments, and return a new state result. In other words, (state, action) => newState.


1 Answers

Mutating state is an anti-pattern in React. React uses a rendering engine which depends on the fact that state changes are observable. This observation is made by comparing previous state with next state. It will alter a virtual dom with the differences and write changed elements back to the dom.

When you alter the internal state, React does not know what's changed, and even worse; it's notion of the current state is incorrect. So the dom and virtual dom will become out of sync.

Redux uses the same idea to update it's store; an action can be observed by reducers which calculate the next state of the store. Changes are emitted and for example consumed by react-redux connect.

So in short: never ever, mutate state. Instead of Object.assign you can use the stage-3 spread syntax:

{...previousState,...changes}

Also please note, this is true for arrays as well!

like image 85
Dennie de Lange Avatar answered Oct 06 '22 09:10

Dennie de Lange