7

When I have the following initial state declared:

  getInitialState: function() {
    return {
      isValid: false,
      metaData: {
        age: 12,
        content_type: 'short_url'
      }
    };
  },

and I update state with setState like this:

...
let newMetaData = {  age: 20 };
...
this.setState({
        isValid: true,
        metaData: newMetaData
      });
...

Resulting this.state.metadata object has only age defined. But as far as I'm aware, this.setState() merges it argument to existing state. Why it's not working here, isn't this supposed to be recurrent merging?

Is there a way to merge new object properties to state object property in React/ES6?

zmii
  • 3,742
  • 2
  • 36
  • 59

3 Answers3

8

setState performs a shallow merge. If metaData is is flat:

this.setState({
  metaData: Object.assign({}, this.state.metaData, newMetaData),
});

or if using spread :

this.setState({
  metaData: { ...this.state.metaData, ...newMetaData },
});
dting
  • 37,400
  • 9
  • 92
  • 114
  • 10
    The spread operator merge isn't a "deep" merge, meaning merges are recursive. Moreover nested object properties aren't merged REF: https://davidwalsh.name/javascript-deep-merge – dodortus Mar 23 '18 at 01:32
1

Another way to approach this, if you only need to update one property, would be like this:

this.setState({
  metaData: {
    ...this.state.metaData,
    age: 20
  }
})
zero_cool
  • 3,494
  • 4
  • 37
  • 50
1

setState can also take a function, which receives an argument of state, and you can use lodash merge to do the deep merge.

  setState(state => merge(state, yourPartialObjectToBeDeepMerged));
httpete
  • 2,389
  • 20
  • 29