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.
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
}
}
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. 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