ReactiveVar object mutations


#1

Here is what I have encountered using ReactiveVar…

Template.Test.onCreated(function(){
  const testDefault = { one: 1, two: 2  };
  console.log('print - 1', testDefault);
  // prints ‘{ one: 1, two: 2  }’ - OK

  this.testReactive = new ReactiveVar(testDefault);
  console.log('print - 2', testDefault);
  // prints ‘{ one: 1, two: 2  }’ - OK

  // now here the fun starts..

  const testVariable = this.testReactive.get();
  testVariable.two = 10;

  console.log('print - 3', this.testReactive.get());
  // it prints { one: 1, two: 10 } even thought I did not set the reactiveVar specifically, expected { one: 1, two: 2 }, not OK

  console.log('print - 4', testDefault);
  // it prints { one: 1, two: 10 } instead of expected { one: 1, two: 2 }, not OK
});

So how come changing the testVariable changes the testDefault variable? Is it ‘normal’? Any ideas, comments?
I have managed to solve it by cloning:

  const testVariable2 =_.clone(this.testReactive.get());
  testVariable2.two = 10;
  console.log('print - 3',  this.testReactive.get());
  console.log('print - 4',  testDefault);
  // it prints { one: 1, two: 2 } in both cases, as expected - OK

But this looks weird and not reliable, as one can forget to clone something and get unintended mutations of initial ‘default’ variables.

You would probably suggest using ReactiveDict for that, and most likely I will have to do so, thought I wanted initially to keep things simple, as in this case I just need an object with 2 values that I will be changing only together.


#2

Well… I have also just found this: https://github.com/meteor/meteor/issues/4414
So this behaviour appears to be a ‘bug’… or a ‘feature’ or at least a known thing… but not documented…


#3

Might be also useful for someone. Whenever I try to do following with ReactiveDict:

const test = new ReactiveDict({one: 1, two: 2});

…it responds with EJSON error, forcing to put values as strings… :-/
So this works fine:

const test = new ReactiveDict({one: '1', two: '2'});

…but looks stupid… :slight_smile: Good thing is that I can retrieve everything with:

console.log('test', test.all());
// -> {one: 1, two: 2}

Still not a best solution in my case. So I have decided to live with the ReactiveVar and _.clone() instead of converting integers to strings to be able to mass set them to a ReactiveDict…

Oh… the world is not perfect…