0

I'm importing redux store and using the spread operator to create a copy of store property. Then when I change this copy, the original property also changes.

When I use copy = JSON.parse(JSON.stringify(original)) everything works fine.

export const move = (moveData: IMove): BoardActionTypes => {
  const { board } = store.getState();
  console.log(board.pieces.byId["19"]); // {row: 3, col: 7}

  const newById: IPiecesById = { ...board.pieces.byId };

  newById["19"].col = 4;
  newById["19"].row = 4;

  console.log(board.pieces.byId["19"]); // {row: 4, col: 4}
  console.log(newById["19"]); // {row: 4, col: 4}

  //...
};
hommat
  • 69
  • 1
  • 6

3 Answers3

2

Your issue is about shallow VS deep copy of an object.

When using spread operator, your creating a shallow copy of an object (Just like when using old-school Object.assign).

When you've used JSON parsing - you get a deep copy (or a "deep clone") of the object.

Shallow copy, as the name suggest, means that the outer object is a new one, while nested objects remains the same. Once you get to know redux in-depth, speard operators should be suffice for most cases, but it is an important difference to keep in mind.

You might want to read my question on this matter, and this article as well,.

yuval.bl
  • 4,890
  • 3
  • 17
  • 31
0

I have 2 options for it.

1. Using underscore.js

var foo = { row: 0, col:0 };
var bar = _.clone(foo);
bar.row = 99;

console.log(foo);
console.log(bar);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>

2. vanilla JS

function clone(obj) {
  if (obj === null || typeof(obj) !== 'object')
  return obj;

  var copy = obj.constructor();

  for (var attr in obj) {
    if (obj.hasOwnProperty(attr)) {
      copy[attr] = obj[attr];
    }
  }

  return copy;
}

var foo = { row: 0, col: 0 };
var bar = clone(foo);
bar.row = 99;

console.log(foo);
console.log(bar);
kyun
  • 9,710
  • 9
  • 31
  • 66
0

What happens to you is - two objects with the same reference.

If you don't want to use an external lib, or a helper function (if you're not going to use it extensively), you can use something like this:

const newById = board.pieces.byId.map((item) => ({ ...item }));

(i assumed byId is an array, and map creates new array)

TValerii
  • 160
  • 1
  • 6