javascriptmeteorpublish-subscribemeteor-blazeminimongo

Meteor Tracker not receiving subscriptions automatically


I'm creating some templates using Template.onCreated, and am then using Tracker.autorun to make some subscriptions and then collect data from the Server and store them on the client's MiniMongo.

Then, I can leave said Template and eventually route myself back. However, I'm noticing that upon coming back, Blaze is not capturing my changes. When routing back, it seems that onRendered is called instead of onCreated. This makes sense, however, onRendered isn't quite reacting to all my data changes yet. I've noticed it's because minimongo doesn't actually have data in it for onRendered.

However, I've noticed it can get the object by refreshing the page (thus calling onCreated and subscribing again and getting a fresh set of data from the server) My workaround is to re-subscribe in onRendered, but I feel like i shouldn't have to do this because I already initially subscribed in OnCreated. Is this an issue with Meteor, is DDP just going slow?

Let's say I have some default generic collection called Objects.

const Objects = new Mongo.Collection("Objects"); 

So in my onCreated I subscribe to a collection as follows

Template.foo.onCreated(function () {
    var self = this;

    self.autorun(function () {
        const objId= FlowRouter.getParam("id");


            self.objectSubscription = Meteor.subscribe('obj', objId, {
                onReady: function () {

                },
                onStop: function (error) {
                    if (error) {
                        alert('error')
                    }
                }
            });

Then in onRendered I have to hack it and unnecessarily re-subscribe because I don't have objId i.e. I can't just use Objects.find(),

Template.foo.onRendered(function () {
    const objId= FlowRouter.getParam("id");

    Meteor.subscribe('obj', objId, {
        onReady: function () {
            $('#obj').addClass('highlight');
        },
        onStop: function (error) {
            if (error) {
                alert('error');
            }
        }
    });

    //I feel like I should just be able to do 
    //const obj = Objects.findOne({_id:objId})
    //$('#obj').addClass('highlight')

});

Any insights, why would I be losing data in minimongo? And is it bad practice to "re-subscribe"?


Solution

  • onCreated and onRendered aren't reactive, but template helpers are. So, to constantly detect changes in those two you'd have to create a reactive context and place it inside them which can be achieved using Tracker.autorun. Also, be advised that it's better to keep onRenderd for DOM manipulations and onCreated for subscriptions and creation of reactive variables.

    You don't need double subscriptions to detect changes and IMO this is generally a bad practice.

    Template.foo.onCreated(function onCreated() {
      const self = this;
      this.autorun(function() {
      const id = FlowRouter.getParam('_id');
      self.subscribe('obj', id);
      });
    });
    
    
    Template.foo.onRendered(function onRendered() {
      const self = this;
      // this will run after subscribe completes sending records to client
      if (self.subscriptionsReady()) {
        // do whatever you want
        $('#obj').addClass('highlight');
      }
    });