Search code examples
loopsmeteorinfinity

Meteor template reload infinity


I have a problem when running with Meteor.

I have a "question" page which I want to increase the count view whenever it is rendered.

So in my template function I write

Template.questionview.helpers({
    question : function() {
      if(Session.equals('main_template_name', 'question')) {
        console.log(Session.get('question_id'));
        Questions.update({
          _id: Session.get('question_id')
        }, {
           $inc: {
           views: 1
        }
     });
   }
});

Now here comes the problem, when I render the question view and update the question item, the view is refreshed again because it is a reflective page. And then it comes infinity loop.

Anyone has suggestions?


Solution

  • Typically, in situations like this, there is something broken about the model. In this case, I believe it's the "count view" idea. There are lots of ways to do this correctly. Incrementing it on render is not, since you're doing model work in UI code (broken conceptually and in implementation).

    First, store the questions the user has visited somewhere. Why not a {questionsVisited:[]} property on the user?

    Use a Meteor.call(...) method call to register a view instead:

    Meteor.methods({
      viewQuestion: function(questionId) {
        // check if the user hasn't visited this question already
        var user = Meteor.users.findOne({_id:this.userId,questionsVisited:{$ne:questionId}});
    
        if (!user)
             return false;
    
        // otherwise, increment the question view count and add the question to the user's visited page
        Meteor.users.update({_id:this.userId},{$addToSet:{questionsVisited:questionId}});
        Questions.update({_id:questionId},{$inc:{views:1}});
        return true;
    });
    

    So how about incrementing the view on UI changes? Well, let's not do that specifically. Let's increment the view count only when the question changes.

    Meteor.autorun(function () {
      var questionId = Session.get("question_id");
      Meteor.call('viewQuestion',questionId,function(e,r) {
        if (r)
          console.log("Question " + questionId + " logged an increment.");
        else 
          console.log("Question " + questionId + " has already been visited by user " + Meteor.userId();
      });
    });
    

    And get rid of all this question helper stuff...

    This is even better than what you originally wanted. Now views aren't counted twice for the same user. If that is the desired behavior, remove the questionsVisited logic.

    Only change the 'question_id' session variable when you actually change the logical question the user is working with.