Meteor.userId() returns an ID, but Meteor.user() returns undefined

Should this be happening? There’s a brief instant (I noticed in my component’s componentDidMount method) where Meteor.userId() returns a valid ID, but Meteor.user() returns undefined. Is this a bug?

I have not checked the accounts package for this, but this kind of makes sense if meteor first sets a user ID, assigning it to Meteor.userId() and then the publication publishes the current user, where Meteor.user() is reactively set as Meteor.users.findOne(Meteor.userId()) on the client, hence that brief gap.

1 Like

Did you ever figure out a way to wait for Meteor.user() to be defined or undefined?

Sure. It’s reactive, so you can easily just wait to use it until it’s defined.

Yeah but in my case I need to do something the second that it’s defined, I can’t just put my check in a setinterval. I was hoping for a meteor.userReady or something.

Oh no, you wouldn’t use setInterval for sure. Like I said, it’s reactive, so you can use Meteor’s createContainer or Kadira’s react-komposer or TrackerReact (whatever suits you, though I prefer the first one).

So what I do is, I have a Meteor container defined with createContainer that might look like this:

import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';
import Something from './Something';

export default createContainer(() => {
  return {
    user: Meteor.user(),
  }
}, Something);

And then in the Something component, you could display something when it’s ready:

render() {
  let name = '???';

  if (this.props.user) {
    name = this.props.user.firstName;
  }

  return <div>
    Some stuff here
    Your name: {name}
  </div>
}

Or if you just need to carry out some action and not display something:

componentWillReceiveProps(nextProps) {
  const user = this.props.user || nextProps.user; // we check both, just in case Meteor.user() is ready right away

  if (user) {
    // do something
  }
}
1 Like

Ahhh interesting, I’ve been trying to get it going in a redux store on
login, and then having that redux store user: Meteor.user() on
initialState.
I’ll have to check out those other packages you mentioned, I was hoping to
just get a promise haha.

Nope. :slight_smile: You’ll have to use something that works with Meteor’s brand of reactivity. Redux won’t work.

Well, it does. With redux-thunk.

actions.js

import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

export const USER_DATA = "USER_DATA";

export function loadUser() {
    return dispatch => {
        Tracker.autorun(() => {
            dispatch({
                type: USER_DATA,
                data: Meteor.user()
            })
        })
    }
}

reducers.js

import { USER_DATA } from './actions'

const initialUser = {
    username: '',
    userid: '',
    email: 
};

function userReducer(state = initialUser, action) {
    switch(action.type) {
        case USER_DATA:
            return {
                username: action.data && action.data.username,
                email: action.data && action.data.emails[0].address,
                userid: action.data && action.data._id
            };
        default:
            return state;
    }
}

and finally main.tsx

import { Meteor } from 'meteor/meteor';
import { loadUser } from 'imports/client/redux/actions';

const store = configureStore(rootState);

Meteor.startup(() => {
  ReactDOM.render(
      <App />,
      document.getElementById("render-target")
  );
  store.dispatch(loadUser());
});

Awesome, I totally forgot about Tracker.autorun(), I assume it just waits until reactive calls can be made?

Usually I put a ton of my logic in regular Meteor.methods and do things pretty traditionally, this is my first foray into the more “meteor”-ish things.

Yes. Works flawlessly for me.

That’s awesome, would love to dig into the internals of whats happening with that tracker call, maybe another time.

@ffxsam: what are the chances I will get the exact same problem? Your answer solved my problem perfectly.

Thank You
Sudheer

1 Like