When/Where to check for roles in a React-Meteor App? Not working at layout level

I do have access to Meteor.userId() in componentWillMount, but for some reason the Roles.userIsInRole is not working because the component is rendered before the full user document makes it to the client (I think).

So what is the best option here? Should I wrap this component in a container with a subscription (in my case, react-komposer)? I could move it to the router in an onChange, but I was having the same issue there.

What’s the cleanest way to figure this out? I have other roles/types beyond admin that I’d like to automatically re-direct if they’re coming back to the site and signed in…so some flexibility there would be good.

export const LandingPageLayout = React.createClass({
  componentWillMount(){

    if (Meteor.userId()) {
      console.log(Meteor.userId()); //logs _id
      console.log(Meteor.user()); //logs undefined
      console.log(Roles.userIsInRole(Meteor.userId(), ['admin'])); //is false even though I know I'm signed in as admin
      if (Roles.userIsInRole(Meteor.userId(), [ 'admin'])) { 
        return browserHistory.push('/admin');
      }

    }
    
  },
  render() {
    return (
        <Layout style={{height: '100vh'}}>
              { this.props.children }
        </Layout>
    );
  }
});

Hello friend,
Have you tried checking if user is in role inside server?

I think you have to assure the data is loaded. One thing you could do it pass the user object authentication through the props and add that to your if statement.

if (this.props.user && Roles.userIsInRole(Meteor.userId(), ['admin'])) {

I am wrapping it up in a container with a subscription - in some kind of a layout component. As I am currently developing my first Meteor + React Application, I can’t say if it is the best solution but it is working for me :wink:

class AdminMainLayout extends React.Component {
  componentWillMount(){
    if(this.props.loading) {
      return (
        <LoadingSpinner /> 
        )
    } else if (!Meteor.user()) {
      return <LoginDialog />
    } else if (!Roles.userIsInRole(Meteor.userId(), ['admin'] )) {
      browserHistory.push('/not-authorized');
    }
  }

  componentDidUpdate(prevProps, prevState){
  // here goes the same as above
  }
  render () {
 const {...props} = this.props;
    if(this.props.loading) {
      return (
        <LoadingSpinner /> 
        )
    } else if (!Meteor.user()) {
      return <LoginDialog />
    } else {
      return (
        <MainLayout {...props} />
      );
    }
  }
}
export default AdminMainLayoutContainer = createContainer(({}) => {
  let currentUserSub = Meteor.subscribe('currentUser');
  let loading = !currentUserSub.ready();
  return {
    loading,
  };
}, AdminMainLayout);

In fact, I think there is no need to check the user’s login status.
There is also no need to check from the server.

 {
  Roles.userIsInRole(Meteor.userId(), ['admin'])
           ?
           <Main />
           :
           <Redirect />
}

In the Meteor.userId () method, null is actually returned if the user is not logged in. And if this null is used in the Roles.userIsInRole(Meteor.userId (), ['admin']) method, it returns false.
In other words, if there is no user or he does not have the necessary status, he returns false in both cases. And if the user logs in, the output is corrected and returns true.