Search code examples
javascriptmeteorreal-time

Why is the template not updating in real time?


I have this Meteor code which is meant to update a notifications' template in real time whenever an appropriate action is triggered:

~/server/app.js

Meteor.methods({
    notifs: function(){
        return Meteor.users.findOne({_id:this.userId}, {'profile.notifs': 1});
    }
});

and:

~/client/apps.js

Template.notifs.helpers({
  notifs: function(){
    Meteor.call('notifs', function(err, data){
      Session.set('notifs', data);
    });
    return Session.get('notifs');
  }
});

finally:

~/public/templates/notifs.html

<template name='notifs'>
    {{#each notifs}}
        <p>...</p>
    {{/each}}
</template>

What this code does for the moment is just listing the notifications when the user logs in, but fails to update in real time to show new notifications as actions are triggered. New notifications show up only after a page refresh (which is, honestly, useless).

After hours of googling I give up and post this here so someone can help me, please.

Thanks in advance.


Solution

  • At it's core, this question is about reactivity. Because Meteor.call isn't a reactive data source (it's just a remote procedure call), the helper won't run again if the underlying data changes.

    Because the necessary user document is already published (it's for the current user), the method call isn't needed. You could rewrite your helper using find (a reactive data source) like this:

    Template.notifs.helpers({
      notifs: function() {
        return Meteor.users.findOne({_id: Meteor.userId()});
      }
    });
    

    However, Meteor.user() gives you the same functionality:

    Template.notifs.helpers({
      notifs: function() {
        return Meteor.user();
      }
    });
    

    However, you don't really even need this because templates come with the {{currentUser}} helper. So you can drop the helper altogether and modify your template like this:

    <template name='notifs'>
      {{#each currentUser.notifs}}
        <p>...</p>
      {{/each}}
    </template>
    

    If you ever actually do need the result of a meteor call in a helper, you should read the answers to this question.