Search code examples
javascriptmeteoriron-router

iron-router not waiting on meteor.user() to return


Solved but looking for improvements, see answers

    function completedProfile() {
        if (Meteor.user() && Meteor.user().profile.primary_email && Meteor.user().profile.display_name && Meteor.user().university_id) {
            return true;
        } else {
            return false;
        }
    }

    Router.map(function() {
        this.route('landing', {
            path: '/', // match the root path
            onBeforeAction: function() {
                this.subscribe('users').wait();
                if (this.ready() && completedProfile()) {
                    this.render('bulletin')
                } else {
                    this.redirect('splash');
                }
            }
        });
    });

The page will redirect to my splash template since the completeProfile function is false (all fields are null in if statement).

Attempt 2 (hangs on splash after fields have been populated):

    Router.map(function() {
        this.route('landing', {
            path: '/', // match the root path
            action: function() {
                if (this.ready() && completedProfile()) {
                    this.redirect('bulletin')
                } else {
                    this.render('splash');
                }
            },
        });

Attempt 3:

    function completedProfile() {
        if (Meteor.user() && Meteor.user().profile.primary_email && Meteor.user().profile.display_name && Meteor.user().profile.university_id) {
            return true;
        } else {
            return false;
        }
    }

    Router.map(function() {
                this.route('landing', {
                    path: '/', // match the root path
                    action: function() {
                        console.log(Meteor.user().profile);  //this fails
                        console.log(this.ready(), completedProfile()); //this then returns as expected
                        if (this.ready() && !completedProfile()) {
                            this.redirect('splash');
                        } else {
                            this.render('bulletin')
                        }
                    },
                });

                this.route('splash', {
                    path: '/splash', // match the root path
                });

                this.route('bulletin', {
                    path: '/bulletin', // match the root path
                });

It's really weird that this works. The log of Meteor.user results in an error and then Meteor.user() loads giving me an appropriate completedProfile() return. The error is Exception in callback of async function: TypeError: Cannot read property 'profile' of undefined .


Solution

  • Looks like you are redirecting to a route named splash. You didn't include it, but I'll assume it exists. Once you've redirected, you're done with any logic for the landing route, so completedProfile() won't be re-run once a user is logged in.

    Try this instead: stay on the landing route, but render() a splash page until the user is logged in.

    if (this.ready() && completedProfile()) {
        this.render('bulletin')
    } else {
        this.render('splash');
    }
    

    I don't think this.subscribe('users').wait(); helps. I'd remove it. I think you also want to use action instead of onBeforeAction since you are calling render() yourself.

    See also: https://github.com/EventedMind/iron-router/issues/91. Sounds like instant login would work well for your use case.