简体   繁体   中英

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');
    }
  }
});

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

You can use Tracker.autorun to 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 });
            }
        });
    }

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM