2

In redux if your action/reducer updates the value of foo.bar and your connected component's mapStateToPropsis (store) => { foo: store.foo } and then passes foo={foo} to a PureComponent child. The child won't rerender when foo.bar changes? That's why they recommend keeping things as flat as possible?

Thanks for the clarification.

Yeah
  • 147
  • 6

1 Answers1

2

There are two questions:

  1. Generally, when does a PureComponent instance update?
  2. Is the PureComponent component instance updating in this example?

Question #1: PureComponent does a shallow comparison of props in shouldComponentUpdate. What this means is described well in the answer to this question. To summarize, a shallow comparison checks for equality of reference rather than equality of value. So, if lastProps.myObj and nextProps.myObj are both references to the same object, a shallow comparison evaluates to true even if lastProps.myObj.foo and nextProps.myObj.foo are not equal.

Question #2: If you have mutated state.foo, so that it's the same object with a changed value, then a shallow comparison will return a false negative. The complicating factor here is that your example uses Redux. You say that a Redux reducer has changed state.foo. One of the first rules of Redux reducers is that they don't mutate state or props. They return a new state. When state is an object, they make a copy of the object and apply the change to the copy. If you are honoring the reducer contract and updating the state without mutating it, then you have changed the reference. In that case, the PureComponent.prototype.shouldComponentUpdate should return true.

// create an object
var foo = {bar: 'bar'};
// make a copy of the object 
var bar = Object.assign({}, foo); 
// both objects look the same, i.e. have the same property with an equal value 
foo.bar === bar.bar // -> true 
// but they are not the same object so the shallow comparison evaluates to false
foo === bar // -> false

So if the PureComponent instance is not updating when state.foo has changed, I would review the reducer that changes foo and make sure the update is not a mutation.

maxhallinan
  • 1,259
  • 2
  • 14
  • 28
  • So a reducer that only updates `a` in `foo.bar.baz.a` would create new objects for `baz`, `bar` and `foo` so that they are new references? And it would go all the way up to the top level key? Would you also create a whole new state reference? What about references for `foo.bar.qux`? Thank you! – Yeah Jul 11 '17 at 02:11
  • The Redux docs answer this question: http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html#updating-nested-objects. – maxhallinan Jul 11 '17 at 14:39