3

One rule of reducer in Redux is: we should treat state as read-only, and return a new object as the new state.

But there is one grey area: must it strictly return a new object as state, or can we return the same state object?

It seems by looking at common code, such as:

function favoriteColors(state, action) {
  if (state === undefined) {
    state = [];
  }

  if (action.type === 'ADD') {
    return Array.from(new Set([...state, action.color]));  // new array
  } else if (action.type === 'REMOVE') {
    return state.filter(color => color !== action.color);  // new array
  } else {
    return state;
  }
}

When the action.type is unknown, then the same state object is returned. So the rule is that the reducer doesn't strictly have to return a new state object, but can return the same one. But the strict rule is that the state must be read-only?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • 1
    I believe your understanding is correct. The rule to be followed is that state is read only. So if your reducer doesn't need to result in a change to state, returning the original state is perfectly acceptable. – JAAulde Feb 11 '20 at 14:17

1 Answers1

5

The rule is that you must not mutate a state object because this can break assumptions made elsewhere in the code. It is OK to return the same state object.

function goodReducer(state, action) {
  return state;
}
function badReducer(state, action) {
  state.counter = (state.counter || 0) + 1;
  return state;
}

The reason for this is that to ensure the rendered DOM is correct and up-to-date, updates to the state must flow through the dispatcher.

In particular:

  • Mutating objects in an uncontrolled can invalidate caches (e.g. shouldComponentUpdate)
  • Mutating objects can cause an inconsistent state to be rendered (e.g. if the mutation happens during a render)

Returning an unmodified state is fine. In fact, libraries like Immutable.js will often do this.

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245