Reactive updates are called too many times
Closed this issue · 4 comments
Here is my code
SERVER
Meteor.methods({
addDialog: function( data ){
db.query('CREATE (:Dialog {id: '+data.id+'})');
AnyDb.refresh( 'allNodes', () => R.propEq('id', data.id) );
}
});
CLIENT
Session.set('nodes', 'loading');
let subscripiton;
export default createContainer(() => {
subscripiton = AnyDb.subscribe('allNodes', {data: 'AKAI'}, ( sub ) => {
log("sub ready");
Session.set('nodes', sub.data);
sub.onChange( (data) => {
log("new sub data")
Session.set('nodes', data);
});
});
return {
nodes: Session.get('nodes'),
};
}, EventsListPage);
My steps:
- i call method once - get "sub ready" and "new sub data" a couple of times in the console
- i call method once more - get "sub ready and "new sub data"" about 6-9 times in the console
- i call method once more time - get "sub ready" and "new sub data" about 10-15 times in the console
and so on...
also my template rerenders multiple times, when it should do only once. Just imagine how many time the update will run if the app will be in production...
it probably has to do with tracker. You're setting a session variable which is tracked with Tracker, and I'm assuming Container is a reactive context as well. Tracker it amazing and magical at first, but as soon as you do anything complicated, its really hard to keep track of whats going on. Its also possible that its cause the subscription to unsubscribe and resubscribe as well.
I'd recommend straying away from Tracker as much as possible. If you're stuck in reactive-land, I'd suggest playing around with Tracker.nonreactive
.
I also have to say that feathers.js basically implements this same thing, but I think even better. I'd highly recommend using it.
Thanks, you were right!
I just moved the subscription part out of the container - now works fine!
Session.set('nodes', 'loading');
let subscripiton = AnyDb.subscribe('allNodes', {data: 'AKAI'}, ( sub ) => {
log("sub ready");
Session.set('nodes', sub.data);
sub.onChange( (data) => {
log("new sub data")
Session.set('nodes', data);
});
});
export default createContainer(() => {
return {
nodes: Session.get('nodes'),
};
}, EventsListPage);
:)
Seriously though, check out feathers.js. They've basically implemented the same thing, only better.