Meteor.users is not ready when Meteor restarts

When developing, everytime I save a file Meteor restarts (which is an excelent feature), however some pages have some validatons based on the user profile and they are redirected to landing page. I was checking and it seems that Meteor.users is not ready yet. How can I sort it?

SpecialController = MainController.extend({
  onBeforeAction: function(){
    const user = Meteor.users.findOne({_id: Meteor.userId()});
    if (user && user.profile.internalStatus == "valid") {
      this.next();
    } else {
     // the routers is sending here but it shouldn't.
      Router.go('dashboard');
    }
  }
});

Upvotes: 0

Views: 154

Answers (3)

dc4ual
dc4ual

Reputation: 93

You can create a function which takes an callback and execute it only when client is ready with all the data needed.

Meteor.runWithFullUser = function(cb) {
  Tracker.autorun((c) => {
    const user = Meteor.user();
    if(typeof user.profile !== 'undefined') {
      cb();
      c.stop();
    }
  });
}

Then use this

SpecialController = MainController.extend({
  onBeforeAction: function(){
    Meteor.runWithFullUser(() => {
      const user = Meteor.users.findOne({_id: Meteor.userId()});
      if (user && user.profile.internalStatus == "valid") {
        this.next();
      } else {
       // the routers is sending here but it shouldn't.
        Router.go('dashboard');
      }
    });
  }
});

In order to make sure that you have Meteor.userId() when you run this method. You have to make sure to render the template only when the Meteor.userId() is present. To do that you can use top level layout template and do something like this

<template name="layout">
  ...
  {{#if currentUser}}
    ...
  {{else}}
    {{> appLayout}}
  {{/if}}
</template>

Hope this will help.

Upvotes: 1

Mostafiz Rahman
Mostafiz Rahman

Reputation: 8552

You won't get the Mereor.userId() immediately, there is a subtle delay for it's readiness.

You can use Tracker.autorunto track the readiness of Meteor.userId(). Tracker.autorun allows a function to be called automatically whenever it's dependent reactive data source changes.

Simply speaking, Tracker.autorun() takes a function as input, runs this function and returns whenever the data source changes later on.

In your case, you can use Tracker.autorun() for tracking the userId, since Meteor.user() and Meteor.userId() are reactive. In componentDidMount() call Tracker.autorun() and save the userId elsewhere when it changes.

Hope following code snippet helps:

componentDidMount() {
        var context = this;

        Tracker.autorun(function() {
            let userId = Meteor.userId();
            if (userId != undefined) {
                context.setState({ userId: userId });
            }
        });
    }

Upvotes: 1

codejockie
codejockie

Reputation: 10892

Using Rahman's answer, you could simply write the code in componentDidMount like this:

componentDidMount() {
   Tracker.autorun(() => {
      let userId = Meteor.userId();
      if (userId != undefined) {
         this.setState({ userId: userId });
      }
   });
}

Arrow function uses its container context as this.

Upvotes: 1

Related Questions