1

In a react app, I have state that looks like this:

dates: {"2015-11-20":{
                      "13:00":{...},
                      "14:00":{...}},
        "2015-11-21":{
                      "18:00":{...},
                      "19:00":{...}}}

I'm running into a problem with updating state - my use case is I want users to be able to copy all the times (e.g. 1pm & 2pm above) to other dates via the UI and have state update accordingly.

So far, all my attempts result in referencing, where the separate objects become linked and any update to one results in an update to the other.

Sample code that produces the broken behaviour:

copyTimes: function() {
      var keys = [];
      Object.keys(this.state.dates).map(function(key) {
          keys.push(key);
      });

      for(var i in keys) {
        this.state.dates[keys[i]] = this.state.dates[this.state.selectedDate];
      }

      this.setState({dates: this.state.dates});
  }

I believe I might need to use the react add on 'update' to solve this, as per https://facebook.github.io/react/docs/update.html

but I can't fully understand the syntax approach I need to take. How do I cause a correct update to 'copy' the contents of one date: '2015-11-20' to another e.g. 2015-11-21 in the above example?

EDIT As per (pointed out in comments): What is the most efficient way to deep clone an object in JavaScript?

  copyTimes: function() {
      var keys = [];
      var tempStart =  JSON.parse(JSON.stringify(this.state.dates));
      Object.keys(this.state.dates).map(function(key) {
          keys.push(key);
      });

      for(var i in keys) {
        tempStart[keys[i]] = JSON.parse(JSON.stringify(this.state.dates[this.state.selectedDate]));
      }

      this.setState({dates: tempStart});
  },

The above works - but is extremely ugly. Is there a better approach?

Community
  • 1
  • 1
Dave
  • 11,392
  • 5
  • 31
  • 42
  • Not sure if it has anything to do with your problem, but from the *big red box* in the [documentation](http://facebook.github.io/react/docs/component-api.html#setstate): *"NEVER mutate `this.state` directly, as calling `setState()` afterwards may replace the mutation you made. Treat `this.state` as if it were immutable."*. I guess what you need is to deep clone `this.state.dates[this.state.selectedDate]`. See http://stackoverflow.com/q/122102/218196 . – Felix Kling Nov 08 '15 at 23:47

1 Answers1

-1

copyTimes: function() {
      var keys = [];
      Object.keys(this.state.dates).map(function(key) {
          keys.push(key);
      });

      var newDates = Object.assign({}, this.state.dates);;
      for(var i in keys) {
        newDates[keys[i]] = this.state.dates[this.state.selectedDate];
      }

      this.setState({dates: newDates});
  }
J. Mark Stevens
  • 4,911
  • 2
  • 13
  • 18