0

I have a react app with an array formatted like so:

var themes = [
  {
    id: 1,
    name: 'Light',
  },
  {
    id: 2,
    name: 'Dark',
  }
];

I have a method inside my React Component that adds a new item to the theme using overrides:

  addTheme = (theme) => {
    const base = themes.find(t => t.name.toLowerCase() === theme.base.toLowerCase());
    var newTheme = base ? base : themes[0];
    console.log(newTheme);
    newTheme.id = themes[themes.length - 1].id + 1;
    newTheme.name = theme.name;
    themes.push(newTheme);
    console.log('themes:', themes);
  };

The issue I am getting is that setting the newTheme variable to the base seems to overwrite the base object in the array.

So if I am adding a theme named Midnight, the Dark theme gets changed also?

logs

Timmo
  • 2,266
  • 4
  • 34
  • 54
  • `var newTheme = base ? base : themes[0];` newTheme is referring to the original one. So you change newTheme property, it also changes to orignal one. Try this: `var newTheme = Object.assign({}, base ? base : themes[0]);` – ninhjs.dev Aug 23 '18 at 15:52
  • 1
    Because it all does with references https://stackoverflow.com/questions/597588/how-do-you-clone-an-array-of-objects-in-javascript – Sumanth Itha Aug 23 '18 at 15:53

3 Answers3

2

You should do a copy of a theme object, because find returns a reference to the object.

You have 2 options - shallow or deep copying the object.

1. Shallow copy (using ES6):

const newTheme = {...base ? base : themes[0]}

2. Deep copy (If you do not have function properties) :

JSON.parse(JSON.stringify(base ? base : themes[0]))

Here's a great discussion about - How do I correctly clone a JavaScript object?.

Jordan Enev
  • 16,904
  • 3
  • 42
  • 67
1

The find() array method will not return a copy of your theme, but rather a reference to it, so you're actually altering the original theme.

Dan
  • 9,912
  • 18
  • 49
  • 70
1

Use Object.assign()

Array.find() method doesn't return a copy of the value matched but the actual matched object from the object array. You need to make a copy of that returned theme object to create the new theme that you wish to add. Object.assign({}, obj) returns a clone of the obj object (mind you, not deep cloning though).

addTheme = (theme) => {
    const base = themes.find(t => t.name.toLowerCase() === theme.base.toLowerCase());
    var newTheme = base ? Object.assign({},base) : Object.assign({},themes[0]);
    console.log(newTheme);
    newTheme.id = themes[themes.length - 1].id + 1;
    newTheme.name = theme.name;
    themes.push(newTheme);
    console.log('themes:', themes);
};
UtkarshPramodGupta
  • 7,486
  • 7
  • 30
  • 54