0

I'm new to React / ES6 and this could be a basic issue. I'm creating a .js file that exports an array of json files. This data is not supposed to change, later when I click a "clear" button, I want to reset my data to the original data from this file. For some reason the data replacements I make to my state, are changing the original import. Any help would be much appreciated. I'm pretty sure I don't need Immutable.js in this scenario but i'm currently using it in hopes to remove this issue, so far it has not worked.

TimerData

const nelths = {
  level: 10,
  endTime: 1980,
  objectives: [
    {
      id: 1,
      objectiveName: "Rokmora",
      objectiveCompleteTime: null
    },
    {
      id: 2,
      objectiveName: "Ularogg Cragshaper",
      objectiveCompleteTime: null
    },
    {
      id: 3,
      objectiveName: "Naraxas",
      objectiveCompleteTime: null
    },
    {
      id: 4,
      objectiveName: "Dargrul",
      objectiveCompleteTime: null
    },
  ],
}
const TimerData = [nelths];
export default TimerData;

Imports

import React, { Component } from 'react'
import TimerData from './timerData'
import FontAwesome from 'react-fontawesome'
import {Map} from 'immutable'

Constructor

constructor(props) {
    super(props);
    //const timerData = Object.assign({}, TimerData[0]);
    var timerData = Map(TimerData[0]);
    this.state = {
        level: timerData.get('level'),
        endTime: timerData.get('endTime'),
        objectives: timerData.get('objectives'),
    }
}

Modification

var objs = this.state.objectives.slice();
objs.forEach(function (element, index, array) {
    element.objectiveCompleteTime = Date.now();
});
this.setState(Object.assign({}, this.state, {objectives: objs}));

Clear

var timerData = Map(TimerData[0]);
this.setState(Object.assign({}, this.state, {objectives: timerData.get('objectives'), active: false}));

I have cut out some of the code to try and save space and show the core components of my state init & modifications. Along with any hints about the issue and tips about bad practices would be appreciated.

Thank you for your time!

Auro
  • 5
  • 2
  • It would be helpful to get the whole component code. Also, did you check the console for errors? – Fabian Schultz Nov 12 '16 at 21:26
  • https://gist.github.com/bae39c9dd49348205599e33a6ade806c - This is a raw code dump, I did check the console for errors. There are none. – Auro Nov 12 '16 at 21:36

1 Answers1

0

Using Immutable.Map doesn't make the values of the Map immutable. You might want to look into using Immutable.fromJS:

As you can see below, the Map's values are references to the values of the object passed to the constructor.

const { Map } = Immutable;

const parent = { child: [] };
console.log('Initial parent.child =', parent.child);

const map = Map(parent);
const mapChild = map.get('child');

console.log('mapChild === parent.child:', mapChild === parent.child);

mapChild.push(1);
console.log('After pushing 1 to mapChild, parent.child =', parent.child);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

const { fromJS } = Immutable;
const timerData = {
  level: 10,
  endTime: 1980,
  objectives: [
    {
      id: 1,
      objectiveName: "Rokmora",
      objectiveCompleteTime: null
    },
    {
      id: 2,
      objectiveName: "Ularogg Cragshaper",
      objectiveCompleteTime: null
    },
    {
      id: 3,
      objectiveName: "Naraxas",
      objectiveCompleteTime: null
    },
    {
      id: 4,
      objectiveName: "Dargrul",
      objectiveCompleteTime: null
    },
  ],
};
    
const data = fromJS(timerData);
    
const updatedData = data.update('objectives', objective => (
  objective.map(value => value.set('objectiveCompleteTime', Date.now()))
));
    
console.log('AFTER - updatedData:', updatedData);
console.log('AFTER - data:', data);
console.log('AFTER - timerData:', timerData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

Depending on what you are looking to do, ImmutableJs might not be needed. You could deep clone the reference object: How to Deep clone in javascript

For your current object, JSON.parse and JSON.stringify would create a deep clone

const nelths = {
  level: 10,
  endTime: 1980,
  objectives: [
    {
      id: 1,
      objectiveName: "Rokmora",
      objectiveCompleteTime: null
    },
    {
      id: 2,
      objectiveName: "Ularogg Cragshaper",
      objectiveCompleteTime: null
    },
    {
      id: 3,
      objectiveName: "Naraxas",
      objectiveCompleteTime: null
    },
    {
      id: 4,
      objectiveName: "Dargrul",
      objectiveCompleteTime: null
    },
  ],
}
    
const cloned = JSON.parse(JSON.stringify(nelths));
console.log(cloned);

cloned.objectives.forEach(objective => (
  objective.objectiveCompleteTime = Date.now()
));

console.log('AFTER');
console.log('cloned', cloned);
console.log('original', nelths);
Community
  • 1
  • 1
dting
  • 38,604
  • 10
  • 95
  • 114