5

Is the following react code wrong ?

state={ foo: { bar: true } }  // line 1
setState(state)               // line 2   
state.foo.bar = false         // line 3
setState(state)               // line 4

If yes, why ?

This suggest that it is wrong, but does not explain why ?

I think it is not wrong, for the following reason:

  • at line 2 vdom1 is created
  • at line 4 vdom2 is created
  • vdom1 and vdom2 are compared
  • difference is propagated to the actual DOM

If this is the case, then mutating state at line3 should not have any effect on what happens at line4.

In other words:

this should be equivalent code:

state={ foo: { bar: true } }  // line 1
setState(state)               // line 2   
state={ foo: { bar: false } } // line 3
setState(state)               // line 4

Is this code equivalent to the one above ?

If not, why not ?

jhegedus
  • 20,244
  • 16
  • 99
  • 167
  • This seems related : http://stackoverflow.com/questions/37755997/why-cant-i-directly-modify-a-components-state-really – jhegedus Oct 24 '16 at 07:54
  • I put a bounty to this related question : http://stackoverflow.com/questions/37755997/why-cant-i-directly-modify-a-components-state-really – jhegedus Oct 24 '16 at 08:44
  • This is related too http://stackoverflow.com/questions/28300547/is-it-a-good-practice-to-modify-a-components-state-and-then-call-setstatethis?rq=1 but does not give an answer – jhegedus Oct 24 '16 at 08:51

1 Answers1

4

Creating an immutable clone of state is a good idea because of the way state changes are compared in order to optimise rendering.

In lifecycle methods like shouldComponentUpdate, nextProps are passed in and can be compared to this.props.

If you mutate the state directly, then nextProps.prop1 and this.props.prop1 will always be the same and therefore you might not get the expected behaviour.

I'm sure there are other reasons as well, but this one seems like the most straight-forward.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • So if I don't use `shouldComponentUpdate` then there is no problem ? – jhegedus Oct 24 '16 at 08:24
  • 2
    There are other lifecycle methods that also can be used to compare props (like `componentWillReceiveProps`, `componentWillUpdate`, and `componentDidUpdate`). And it should be noted that you may not use these *now*, but want to use the *later* when things get slow. – Davin Tryon Oct 24 '16 at 08:58
  • 1
    So if I don't use any lifecycle methods then it is fine, but otherwise if I want to compare new and old state/props (anywhere) then I cannot directly mutate state. Right ? I mean, it depends on what I do. If I don't compare old and new state/props myself, then it's just fine, react will never want to compare old and new state/props itself, right ? So react has no hidden magic by default that tries to compare old and new state. Right ? – jhegedus Oct 24 '16 at 09:05
  • 1
    To be honest, I'm not 100% sure that the React internals make use of this. the vdom or diffing algorithm could assume that the state is not the same as well. – Davin Tryon Oct 24 '16 at 09:55
  • Ok, interesting ! Thanks ! – jhegedus Oct 24 '16 at 15:24