React Meteor.user().username


#1

Hello!

Been following the react guide and i want to display the users username on the page like i would in blaze.

From the guide:
In your data container, you can use Meteor.user() to check if a user is logged in and get information about them. For example, Meteor.user().username contains the logged in user’s username. You can also use Meteor.userId() to just get the current user’s _id.

This works perfectly

{ this.props.currentUser ? 'logged in' : 'not logged in' }

However, i just cant figure out how to DISPLAY the username on the page.
{ this.props.currentUser.username } gives the following error:

Invariant Violation: Objects are not valid as a React child (found: object with keys {_id, username}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of 'App'.

How am i supposed to do?

Thanks!


#2

Can you show us your App component source?


#3

This is my entire App.jsx

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { createContainer } from 'meteor/react-meteor-data';

import Logo from './Logo.jsx';
import Account from './Account.jsx';
import Recipes from './Recipes.jsx';
import Recipe from './Recipe.jsx';
import AccountsUIWrapper from './AccountsUIWrapper.jsx'

// App component - represents the whole app
class App extends Component {
  render() {
    return (
      <div>
        
        //works
        { this.props.currentUser ? 'logged in' : 'not logged in' }

        //doesnt work - throws error (as described above "Invariant Violation")
        { this.props.currentUser }

        //doesnt work - throws error (.username is not defined)
        { this.props.currentUser.username }

        <div className="sidebar">
          <Logo />
          <Recipes />
          <AccountsUIWrapper />
          <Account />
        </div>

        <div className="container">
          <Recipe />
        </div>

      </div>
    );
  }
}

App.propTypes = {
  currentUser: PropTypes.object,
};

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

#4

Okey i finally figured it out.

I can use { this.props.currentUser.username }

inside
{ this.props.currentUser ? <span>{ this.props.currentUser.username }</span> : '' }

not outside. Seems super weird to me. Is this… true?


#5

Try:

{ this.props.currentUser ? `${this.props.currentUser.username}` : '' }

#6

Yea i misspelled, “cant” instead of “can”. I (can) use currentUser.username inside. Not outside. Can you explain why? Thanks for the help!


#7

Meteor.user() is a reactive data source. That means it could be null for a bit before your user record is loaded and ready. So within your App component, your currentUser prop has an initial value of null. You can’t reference this.props.currentUser.username until currentUser exists, which is why it works within your this.props.currentUser ? ... check (since that check makes sure the currentUser exists first before referencing the username property).


#8

JS won’t let you try to access a property of undefined or null

Meteor.user() is null if the user isn’t logged in, so this error can appear when the component gets rendered before the user is logged in by the client

So you should check that the object exists or use a default:

export default createContainer(() => {
  return {
    currentUser: Meteor.user() || {}, // default to plain object
  };
}, App);

and then you can do

// component
<div>
  // etc.
  {currentUser.username || ''}
</div>

A lil gotcha, just in case -

{ this.props.currentUser ? 'logged in' : 'not logged in' }

will always be ‘logged in’ if you default to an object


#9

Thanks for the help! I understand how it works, finally :slight_smile: