Conditional rendering with if/else render should have return statement

I'm trying to render diferent UIs based on user roles, now I'm testing with just one role but I'm having a problem with the render method.

first I have this

 <AuthUserContext.Consumer>
 { authUser => 
   authUser
   ? <NavigationAuth authUser = {authUser} />
   : <NavigationNonAuth />
 }
 </AuthUserContext.Consumer>

I check if user is logged or not, then on NavigationAuth I decide what to render based on its role with this

render(){

this.props.authUser.getIdTokenResult()
.then((idTokenResult) => {
   if (!!idTokenResult.claims.student) {
       // eslint-disable-next-line
       console.log("I'm a student")
   return (<NavigationStudent/>);

   } else {
       // eslint-disable-next-line
       console.log("I'm not a student")
   return (<NavigationNonAuth/>);
   }
})
.catch((error) => {
  console.log(error);
  return <NavigationNonAuth/>;
});

}

But react gives me this error Your render method should have return statement I don't understand why because there is a render on three possible options, if and else statement and the catch

How can I change the code to work this way?

Edit:

if I understood well, this.props.authUser.getIdTokenResult() retuns a promise object, then I'm doing as other post says a solution to get async request so I tried this

   showStudentUI() {
    console.log("I'm student on showStudentUI");
    <NavigationStudent/>
}

showSomethingUI = () =>
    <NavigationNonAuth/>

render(){
    this.props.authUser.getIdTokenResult(true) //this is a PROMISE item
    .then((idTokenResult) => {
        if (!!idTokenResult.claims.student) {
            // eslint-disable-next-line
            console.log("I'm a student")
            return this.showStudentUI();

        } else {
            // eslint-disable-next-line
            console.log("I'm not a student")
            this.showSomethingUI();
          }
     })
     .catch((error) => {
       console.log(error);
       return <NavigationNonAuth/>;
     });

   console.log("I'm nothing yet")
   return <div></div>
 }

  }

and with a Student I get the following console.logs

I'm nothing yet

I'm a student

I'm student on showStudentUI

so... the callback after the promise is resolved I think is doing fine, the problem here I think its that my component are not rendered again?

I may be wrong, its my first time facing asyc problems

source about return type for getIdTokenResult: https://firebase.google.com/docs/reference/js/firebase.User#getIdTokenResult

1 answer

  • answered 2018-07-11 07:42 JoseCarlosPB

    I've managed to make it work with the following code

    class NavigationAuth extends Component {
    constructor(props,context) {
    super(props,context);
    this.state = ({value:0,gotUserRole:false});
    
    
    render() {
       console.log(this.state.gotUserRole);
       console.log(this.state.value);
     if(this.state.gotUserRole === false) {
        this.props.authUser.getIdTokenResult(true) //this is a PROMISE item
        .then((idTokenResult) => {
            if (!!idTokenResult.claims.student) {
                // eslint-disable-next-line
                console.log("I'm a student")
                this.setState({value:1,gotUserRole:true})
                return <div></div>;
    
            } else {
                // eslint-disable-next-line
                console.log("I'm not a student")
                this.setState({value:2,gotUserRole:true})
                return <div></div>;
              }
         })
         .catch((error) => {
           console.log(error);
           this.setState({value:3,gotUserRole:true})
           return <div></div>;
         });
         return <div></div>
     }
    else if(this.state.value===1) {
        console.log("Now on student value");
        return <NavigationStudent/>;
    }
    else if(this.state.value===2) {
        console.log("Now on admin value");
        return <NavigationAdmin/>;
    }
    else {
        console.log("not known role");
        return <NavigationNonAuth/>
    }
    }
    
    }
    

    I'm sure this ''fix'' is a very bad one, if someone knows how should I do this with a proper way, thanks in advance

    With this fix I'm first recovering the user role and force a re-render with setState, on the 2ยบ render I'm only rendering the correct UI based on the user role