How to avoid Meteor.loggingIn waiting for subscriptions to finish


#1

Hi!

I’m using Meteor 1.8.0.2 with React and withTracker. My component looks like this:

export default withTracker(() => {
    return {
        loggingIn: Meteor.loggingIn(),
        subLoading: !Meteor.subscribe('foo').ready()
    }
})(SomeComponent);

The problem is, that Meteor.loggingIn() returns only true after the subscription is finshed loading. But it should change to loggedIn==true before it starts to load the subscription.

This only happens when I run Meteor.loginWithPassword. When I refresh the page It works as expected.


#2

Not sure if this is what you are requesting, but I have 2 checks (no what kind of app though. Have a similar setup in NextJS with Apollo).

  • A session check. (Checking if the cooke / jwt is present in the browser). In Meteor you could simply use Meteor.userId(). Which (if the session is set) will have a value right away on browser / app load
  • A user details check. I’m using Meteor.user() for that (In case of an additional subscription I’m using the ready state of that subscription.

It’s not yet published, but here’s my VueX Meteor store plugin. It gives you a clue on how I solve these things:

/**
 * This plugin tracks the user\'s session with Meteor Tracker and
 * keeps it in sync with the Vuex user store
 * @param store
 */
export default (store) => {
  /**
   * Tracks changes on the user
   */
  if (Meteor.isClient) {
    Tracker.autorun(() => {
      const user = Meteor.user();

      if (user) {
        store.commit('setUser', user);
      }
    });

    /**
     * Tracks if the user is logging out
     */
    Tracker.autorun((c) => {
      const userId = Meteor.userId();

      // The Meteor.userId state is never set on the firstRun (refresh or initial load) so skip that
      if (c.firstRun) {
        return;
      }

      // Only commit 'unsetUser' when userId was changed and set to empty
      if (!userId) {
        store.commit('unsetUser');
      }
    });
  }
};

Then in my store it looks like this:

export default {
  state: {
    userId: Meteor.userId(), // On initial load the userId will come from Meteor's session
    email: null,
    isEmailVerified: null,
    profile: null,
    userDetailsLoaded: false,
  },
  mutations: {
    unsetUser(state) {
      state.userId = null;
      state.email = null;
      state.isEmailVerified = null;
      state.profile = null;
      state.userDetailsLoaded = false;
    },
    setUser(state, { _id, emails, profile }) {
      const { address, verified } = emails && emails[0] ? emails[0] : {};
      state.userId = _id;
      state.email = address;
      state.isEmailVerified = verified;
      state.profile = profile;

      // In Meteor the Meteor.userId() can be set while Meteor.user() is still empty
      // This is because the Meteor.userId() comes from the session cookie and Meteor.user()
      // gets its data from a publication. Each new login of page refresh, the client will
      // subscribe to the server and during that time Meteor.user() will be empty
      // The userDetailsLoaded will mark that Meteor.user() is filled on 'true'
      if (!state.userDetailsLoaded) {
        state.userDetailsLoaded = true;
      }
    },
  },
}

#3

No, this is not what I’m looking for… Your code does not use Meteor.loggingIn. but that was the whole point here.