currentUser: undefined | React + Meteor

I’m creating a new project to get acquainted with using React and Meteor together. I’m following along with the docs but have a problem with reactive data, particularly Meteor.user().

http://react-in-meteor.readthedocs.org/en/latest/meteor-data/#preventing-extra-re-renders-from-new-data

The following code snippet does not work for me:

var HelloUser = React.createClass({
  mixins: [ReactMeteorData],
  getMeteorData() {
    return {
      currentUser: Meteor.user()
    };
  },
  render() {
    return <span>Hello {this.data.currentUser.username}!</span>;
  }
});

When I try this in my code I get these errors:

Cannot read property ‘username’ of undefined
&
Cannot read property ‘_currentElement’ of null

However, if I:
let { currentUser } = this.data;
inside of the render function, and then log { currentUser },
it runs twice, the first time returning undefined, and the second time returning the correct object.

For what its worth, I am trying to render the username of the current user inside the header of my page, and I am using kadira:react-layout to render the header component as part of a layout.

Any ideas why I’m having this problem?

1 Like

basically react is not waiting user to return data before it renders it self, so intially your currentUser is null until the subscription is connected and data is fetched.

To avoid this you can put this in the render method

let renderContent;
if(this.data.currentUser){
    renderContent = <span>Hello {this.data.currentUser.username}!</span>;
}else{
    //you can do a loading template here or just leave blank
}

return renderContent;
1 Like

do you have fast-render installed ?

Thanks @sikanx, is implementing the workaround like you suggested the only way to solve this? Why isn’t this mentioned in the Meteor React docs?

@shock nope

this.data.x is almost the same as this.state, as you know about states, states are initially null unless you give them a default value.

But i think another work around is to pull the data in a container component and pass the data down as PROPs to the page

Your issue is that of a race condition as @sikanx mentioned but I think @shock has pointed out a better solution if fast render does server side rendering before passing the first page to you which would eliminate any race condition.

Fast render runs the waitOn function (or one of the Fast Render API calls) on the server and gets the subscription data relavant to the page you are loading. Then it sends that data along with the initial HTML

and what if I want to make a subscribe inside a react component?

You’d do that in the Router such as flow router

No, don’t do subscriptions in the router! Very bad. Subscribe in getMeteorData().

MyComponent = React.createClass({
  mixins: [ReactMeteorData],
  
  getMeteorData() {
    const handle = Meteor.subscribe('someThings');
    
    return {
      ready: handle.ready(),
      things: Things.find().fetch()
    }
  },
  
  render() {
    if (!this.data.ready) {
      // show loader or something
      return <MyLoader />;
    }
    
    return <div>...</div>
  }
});
1 Like

And why is that? Subscribing in the router solves my issue when firefox complains about Meteor.user(...) is undefined

I’ll rephrase a bit. :slight_smile: It’s doable, but not recommended. Works better in Iron Router than Flow Router BTW, since Flow Router is not reactive (and routers shouldn’t be)… plus Flow Router will eventually be dropping subscription support anyway.

This is worth a read: https://www.discovermeteor.com/blog/template-level-subscriptions/

There’s probably some other way to fix your Meteor user undefined issue.

2 Likes