devdevdove
devdevdove

Reputation: 1

Why do changes to a plain object affect a reactive object when they are not the same?

I have the following piece of code:

const cellsArray = Array.from(Array(fieldSize.height), (_, y) =>
  Array.from(Array(fieldSize.width), (_, x) => new Cell(y, x))
);

const fieldCells = ref(cellsArray);

console.log(fieldCells.value[0][0] == cellsArray[0][0]);    // false

function increase() {
  cellsArray[0][0].x += 1;

  console.log(cellsArray[0][0].x);          // 1, 2, 3, 4 and so one
  console.log(fieldCells.value[0][0].x);    // 1, 2, 3, 4 and so one
}

I create a 2D array of Cell class instances - cellsArray. Then I make a reactive array fieldCells from the plain one. As far as I know ref wraps the cellsArray into a Proxy so fieldCells is a different array. I can see it when I log fieldCells.value[0][0] == cellsArray[0][0] because it prints false. So the [0][0] elements in both arrays do not point to the same object. But!! When I increase the x value in one of the element of any of the arrays, the changes affect the element on the same position in the other array. For example, if I do cellsArray[0][0].x += 1 then fieldCells.value[0][0].x will also increase by one. I don’t understand why this happens when the corresponding elements point to different objects.

The official documentation says that the ref wraps all nested properties so they should be different from the plain object properties.

Upvotes: 0

Views: 143

Answers (1)

yoduh
yoduh

Reputation: 14709

Sorry I misunderstood your question with my original answer (deleted it). The actual answer is that while they are separate objects in terms of equality, by its nature a proxy object is still going to mutate the original object you give it. That's why updating the ref object updates the original, and updating the original updates the ref because Vue has specifically modified Proxy refs to do that to create reactivity.

To prevent these two objects from affecting each other, you need to deep copy the original object during assignment, e.g.

const fieldCells = ref(JSON.parse(JSON.stringify(cellsArray)));

see this codesandbox for a working example.

Upvotes: 0

Related Questions