REACT - Check authentication before render APP

Im really stuck here and im not sure why, im kind of new to React so every help i can get would be consider great :D!

I have stored a JWT token inside localstorage when USER is signed in, when we refresh the page i have this function to check if the user is authenticated so we can set the user again.

async checkLoginStatus() {
    console.log('checking');
    const token = localStorage.getItem('sid');
    if (token) {
      let user = await VerifyUser(token);
      if (user) {
        this.setState({
          isLoggedin: true,
          user: user
        });
      } else {
        this.setState({
          isLoggedin: false,
          user: {}
        });
      }
    } else {
      this.setState({
        isLoggedin: false,
        user: {}
      });
    }
  }

  componentDidMount() {
    this.checkLoginStatus();
  }

Here is my routes atm, dont mind the diff of the codes, testing some stuff

<Router>
            <Header handleLogin={this.handleLogin} isLoggedin={this.state.isLoggedin} handleLogout={this.handleLogout} />
            <Switch>
              <Route exact path="/about" component={About} />
              <Route exact path="/portfolio" component={Portfolio} />
              <Route exact path="/" component={ () => <Home user={this.state.user}/> } />
              <PrivateRoute exact path="/user" isLoggedIn={this.state.isLoggedin} component={User} />
            </Switch>
        </Router>

Here is my PrivateRoute

const PrivateRoute = ({ component: Comp, isLoggedIn, path, ...rest }) => {
    return (
      <Route path={path} {...rest} render={props => {
          return isLoggedIn ? (<Comp {...props} />) : (<Redirect to="/" />);
        }}
      />
    );
  };

export default PrivateRoute;

When the user is logged in they can access the Protected page, but when they are logged out they cannot. So that works fine. And when i refresh page anywhere on the site, it checks if we have a token and it login the user, this is not the problem aswell.

The problem is when i am standing on /user <- the protected page, and i refresh page, the user is not logged in, i guess because the function where we check the user to be logged in has not been done yet when we try to render that route. Ive tried changing componentDidMount to componentWillMount with no results.

Any suggestions?

Upvotes: 7

Views: 11050

Answers (1)

Aprillion
Aprillion

Reputation: 22324

The problem is that initial value of isLoggedIn is falsey, which triggers the redirect (before the state is updated asynchronously):

isLoggedIn ? (<Comp {...props} />) : (<Redirect to="/" />)

What you need is 3 states for 'loading', 'login succes' and 'login fail'.

Example with 2 boolean variables:

state = {
  isLoading: true,
  isLoggedIn: false,
  user: {}
}
...
    this.setState({
      isLoading: false,
      isLoggedIn: false
    })
...
    isLoggedIn ? (<Comp {...props} />) : (isLoading ? 'Loading...' : <Redirect to="/" />)

(the same can be achieved with initial state isLoggedIn: null and condition isLoggedIn === null if you prefer fewer variables)

Upvotes: 9

Related Questions