1

A very simple App. At the / path I want to render Home when logged in and Introduction if not signed in. Logging in on the Login page works, if i console.log(firebase.auth().currentUser) it shows all the data and on / it renders Home correctly. So, while still being at the / path, something weird happens; when i refresh page we are not logged in anymore and it renders Introduction. But when I click on the link <li><Link to='/'>Home</Link></li> the Home component renders correctly and we are logged in again. Why is this happening?

import React, { Component } from 'react';
import {BrowserRouter as Router, Route, Switch, Link, Redirect} from 'react-router-dom';
import firebase from './firebase'

import Home from './containers/home'
import Login from './containers/login'
import Register from './containers/register'
import Dashboard from './containers/dashboard'

const Protected = ({component: Component, ...rest}) => (
  <Route {...rest} render={(props) => {
    if(firebase.auth().currentUser) 
      return <Component {...props} />
     else 
      return <Redirect to='/register' />

  }} />
)

const Introduction = props => ( <h1>hello</h1>)

class App extends Component {


  render() {
    return (
      <Router>
        <React.Fragment>
          <ul>
            <li><Link to='/'>Home</Link></li>
            <li><Link to='/register'>Register</Link></li>
            <li><Link to='/login'>login</Link></li>
            <li><Link to='/dashboard'>dashboard</Link></li>
          </ul>
          <Switch>
            <Route path='/' exact render={(props) => {
              if(firebase.auth().currentUser) 
                return <Home {...props} />
              else
                return <Introduction {...props} />
              }
            } />
            <Route path='/register' exact component={Register} />
            <Route path='/login' component={Login} />
            <Protected path='/dashboard' component={Dashboard} />
          </Switch>
        </React.Fragment>
      </Router>
    );
  }
}

export default App;

1 Answer 1

1

Here's what happens:

  • Webpage loads
  • Firebase starts a request to check whether the user is authenticated
  • The app renders, currentUser is null
  • The authentication state changes, but the app doesn't re-render

The app needs to listen to changes in the authentication state and perform a re-render accordingly. https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged

class App extends React.Component {
  state = {
    currentUser: null
  }

  componentDidMount() {
    this.unsubscribe = firebase.auth().onAuthStateChanged(currentUser => {
      this.setState({ currentUser })
    })
  }

  componentWillUnmount() {
    this.unsubscribe()
  }

  render() {
    // use this.state.currentUser
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This behavior is problematic if you are using authenticated routes and redirecting users to a login page. The app renders, current user is null, redirects to login page before firebase has a chance to initialize.
Not sure I understand. It might initially show a login page, but if the user is authenticated, the state will update and show the dashboard. What's your suggested alternative?
@kindaro I'm not aware of any solution (still looking) other than to wait for the login state before rendering anything in react. What you mentioned is fine (flash login page and then refresh to logged-in page after status) if it's a SPA, but if you are redirecting user to a separate login URL then it becomes a problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.