Search code examples
javascriptmeteoriron-router

Not found page pops up for a second - Meteor - iron - router


I upgraded my app to Meteor 1.0 and updated the my router.js, because I can't use .wait() anymore. However, now my not found page pops up for just a second, before the 'real page' shows up. How can I fix this?

Here is my code:

this.route('gamePage', {
        path: '/game/:slug/',
        onBeforeAction: [function() {
            this.subscribe('singlePlayer', this.params.slug);
            var singlePlayer = this.data();
            if (singlePlayer) {
                if (singlePlayer.upgrade) {
                    this.subscribe('upgrades', this.params.slug);
                }
            }
            this.next();
        }],
        data: function() {
            return Games.findOne({slug: this.params.slug});
        },
        waitOn: function() { return [Meteor.subscribe('singleGame', this.params.slug)]}
    });

Any help would be greatly appreciated.


Solution

  • Try using the subscriptions pattern instead.

    this.route('gamePage', {
        path: '/game/:slug/',
        subscriptions: function() {
            return Meteor.subscribe('singlePlayer', this.params.slug);
        },
        onBeforeAction: function() {    
            var singlePlayer = this.data();
            if (singlePlayer) {
                if (singlePlayer.upgrade) {
                    this.subscribe('upgrades', this.params.slug);
                }
            }
            this.next();
        },
        data: function() {
            return Games.findOne({slug: this.params.slug});
        },
        waitOn: function() { return [Meteor.subscribe('singleGame', this.params.slug)]}
    });
    

    However, it is important that you also include the loading plugin to take advantage of the loadingTemplate.

    Router.configure({
        loadingTemplate: 'loading' // general purpose loading template
    });
    
    // built in plugin.. surprisingly not clearly specified in current docs, but you can dive in the code for plugins. 
    // https://github.com/EventedMind/iron-router/blob/devel/lib/plugins.js
    
    Router.onBeforeAction('loading', { only: ['gamePage'] }); // only show loading for pages with subscriptions
    
    Router.map(function() {
      this.route('gamePage',{
          //... your other options here ..
          loadingTemplate: 'gamePageLoading', // game Page dedicated loading markup.
      });
    });
    

    There's also the this.ready() pattern if you'd like to stay at your onBeforeAction implementation.

    this.route('gamePage', {
        path: '/game/:slug/',
        onBeforeAction: [function() {
            this.subscribe('singlePlayer', this.params.slug);
    
            if(this.ready()) {
                var singlePlayer = this.data();
                if (singlePlayer) {
                    if (singlePlayer.upgrade) {
                        this.subscribe('upgrades', this.params.slug);
                    }
                }
                this.next();
            } else {
                this.render('loading');
            }
    
        }],
        data: function() {
            return Games.findOne({slug: this.params.slug});
        },
        waitOn: function() { return [Meteor.subscribe('singleGame', this.params.slug)]}
    });
    

    Source: https://github.com/EventedMind/iron-router/blob/devel/Guide.md#subscriptions

    I think this change was necessary because the .wait pattern was viewed as unnecessary chaining and is prone to (coding) errors. Additionally, explicitly handling the .next() when overriding onBeforeAction now ensures proper timing of this hook (and probably most, if not all other hooks).