How to update nested state properties in React

后端 未结 26 2431
野趣味
野趣味 2020-11-21 06:35

I\'m trying to organize my state by using nested property like this:

this.state = {
   someProperty: {
      flag:true
   }
}

But updating

26条回答
  •  遥遥无期
    2020-11-21 07:22

    Disclaimer

    Nested State in React is wrong design

    Read this excellent answer.

     

    Reasoning behind this answer:

    React's setState is just a built-in convenience, but you soon realise that it has its limits. Using custom properties and intelligent use of forceUpdate gives you much more. eg:

    class MyClass extends React.Component {
        myState = someObject
        inputValue = 42
    ...
    

    MobX, for example, ditches state completely and uses custom observable properties.
    Use Observables instead of state in React components.

     


    the answer to your misery - see example here

    There is another shorter way to update whatever nested property.

    this.setState(state => {
      state.nested.flag = false
      state.another.deep.prop = true
      return state
    })
    

    On one line

     this.setState(state => (state.nested.flag = false, state))
    

    note: This here is Comma operator ~MDN, see it in action here (Sandbox).

    It is similar to (though this doesn't change state reference)

    this.state.nested.flag = false
    this.forceUpdate()
    

    For the subtle difference in this context between forceUpdate and setState see the linked example.

    Of course this is abusing some core principles, as the state should be read-only, but since you are immediately discarding the old state and replacing it with new state, it is completely ok.

    Warning

    Even though the component containing the state will update and rerender properly (except this gotcha), the props will fail to propagate to children (see Spymaster's comment below). Only use this technique if you know what you are doing.

    For example, you may pass a changed flat prop that is updated and passed easily.

    render(
      //some complex render with your nested state
      
    )
    

    Now even though reference for complexNestedProp did not change (shouldComponentUpdate)

    this.props.complexNestedProp === nextProps.complexNestedProp
    

    the component will rerender whenever parent component updates, which is the case after calling this.setState or this.forceUpdate in the parent.

    Effects of mutating the state

    Using nested state and mutating the state directly is dangerous because different objects might hold (intentionally or not) different (older) references to the state and might not necessarily know when to update (for example when using PureComponent or if shouldComponentUpdate is implemented to return false) OR are intended to display old data like in the example below.

    Imagine a timeline that is supposed to render historic data, mutating the data under the hand will result in unexpected behaviour as it will also change previous items.

    Anyway here you can see that Nested PureChildClass it not rerendered due to props failing to propagate.

提交回复
热议问题