I migrated a piece of code from Session to ReactiveDict. After some debugging it appears ReactiveDict is not triggering any recomputation event when the { key : value } pair is added to the dictionary.
var selected = new ReactiveDict()
Meteor.autorun(function() {
for (var k in selected.keys)
console.log("reactiveDict", k, " : ", selected.get(k))
})
Meteor.setTimeout(function () { selected.set('test', true) }, 1000)
Meteor.setTimeout(function () { selected.set('test', false) }, 2000)
Meteor.setTimeout(function () { selected.set('test', true) }, 3000)
Meteor.setTimeout(function () { selected.set('test', false) }, 4000)
That code doesn't print anything whereas the following works
Meteor.autorun(function() {
for (var k in Session.keys)
console.log("session", k, Session.get(k))
})
Session.set('test', true)
It prints "session test true" (Session is saved across client updates, therefore one needs to make sure to start with a fresh environment for the test to be valid)
My understanding was that ReactiveDict was a drop-in replacement of Session (actually that it was the code of Session made available into a package). But in this case they behave very differently.
The only workaround I found is to force the react trigger with an artificial variable that already exists
var selected2 = new ReactiveDict()
selected2.set('workaround', false)
Meteor.autorun(function() {
for (var k in selected2.keys)
{
var v = selected2.get(k)
if (k != "workaround") console.log("selected2", k, " : ", v)
}
})
var selected2_set = function (key, value) {
var w = (selected2.keys[key] == undefined)
selected2.set(key, value)
if (w) {
selected2.set('workaround', true)
selected2.set('workaround', false)
}
}
Meteor.setTimeout(function () { selected2_set('test', true) }, 1000)
Meteor.setTimeout(function () { selected2_set('test', false) }, 2000)
Meteor.setTimeout(function () { selected2_set('test', true) }, 3000)
Prints "selected2 test : true", then false, then true
My questions are
The only "improvement" of the workaround that comes to my mind is allowing 'workaround' to alternate between true and false, but that creates other types of issues like not being able to iterate just looking for true values.
Also, one has to be careful not to filter 'workaround' out because then the recomputation is not properly triggered. For instance the following change in the autorun doesn't work because get('workaround') never gets ran.
if (k != "workaround") console.log("selected2", k, " : ", selected2.get(k))
keys
is simply a property of the ReactiveDict
and does not register a reactive dependency so this behavior is expected. In the current implementation (meteor v1.1) there isn't an easy way to achieve what you are looking for.
In an upcoming version, all
will set up a reactive dependency on all of the keys, so this will work:
Tracker.autorun(function() {
_.each(selected.all(), function(value, key) {
console.log(key + ":" + value);
});
});
If you want to use that version now, you can download the source to a file called lib/reactive-dict2.js
and replace any reference to ReactiveDict
with ReactiveDict2
(currently lines 19 and 43 - note this is critical or other parts of your app may break). Then you can do this to use it:
var selected2 = new ReactiveDict2()
And the above code should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With