title: Problem with protected routes, context API and firebase user authentication request
body: <p>I am writing a basic CRUD React app that uses Firebase for authentication. At the moment I am trying to create a protected route for a component named <strong>Dashboard</strong>. The protected route insures that any encapsulated routes (such as the Dashboard) do not render unless the user is authenticated.If the user is not authenticated then the router redirects to the landing page.</p>
  
  <p>The way that I am accomplishing this is modelled on <a href="http://%20https://medium.freecodecamp.org/how-to-protect-your-routes-with-react-context-717670c4713a" rel="nofollow noreferrer">this</a> article:</p>
  
  <p>I have emulated the pattern in the article above and it works fine. When I incorporate firebase (specifically firebase authentication) my app does not render the <strong>Dashboard</strong> component even when a user has logged in. Instead it simply redirects to the landning page</p>
  
  <p>I know what the problem is (I think) but I am unsure how to fix it.</p>
  
  <p>The problem is that the call to firebase is an async operation and the dashboard attempts to load before the call to firebase is resolved.</p>
  
  <p>I want to know if their are any tweaks to my code I can make to fix this.</p>
  
  <p>I could make an api call to firebase <em>every time</em> the user loads a protected route (to check for authentication) but I would prefer to set the authentication on the state of the Context and reference that state until the user either logs in or logs out.</p>
  
  <p>I've placed the relevant code below. All files are in the <code>src</code> directory</p>
  
  <p>Thank you!</p>
  
  <p><strong>App.js</strong></p>
  
  <pre><code>import React, { Component } from 'react';
  import { BrowserRouter, Route, Redirect } from "react-router-dom";
  import {Switch} from 'react-router';
  import Landing from './PageComponents/Landing';
  import {Provider} from './PageComponents/Context';
  import Dashboard from './PageComponents/Dashboard';
  import ProtectedRoute from './PageComponents/ProtectedRoute';
  
  class App extends Component {
    render() {
      return (
        &lt;div className="App"&gt;
  
        &lt;Provider&gt;
          &lt;BrowserRouter&gt;
  
          &lt;div&gt;
            &lt;Switch&gt;
  
              &lt;Route exact={true} path="/" component={Landing} /&gt;
              &lt;ProtectedRoute exact path="/dashboard" component={Dashboard} /&gt; 
  
            &lt;/Switch&gt;
          &lt;/div&gt;
  
          &lt;/BrowserRouter&gt;
          &lt;/Provider&gt;
  
        &lt;/div&gt;
      );
    }
  }
  
  export default App;
  
  
  </code></pre>
  
  <p><strong>PageComponents/Context.js</strong></p>
  
  <pre><code>import React from 'react';
  import { getUser } from '../services/authentication';
  
  let Context = React.createContext();
  
  class Provider extends React.Component {
  
      state = {
          userID: true,
          user:undefined,
          authenticated:false
      }
  
      async getUser(){
  
          try{
  
              let user = await getUser();
  
              return user
  
          } catch(error){
  
              console.log(error.message)
          }
  
      }
  
  
      async componentDidMount(){
  
          console.log("waiting to get user")
          let user = await this.getUser();
          console.log(user)
          console.log("got user")
  
          this.setState({
            userID: user.uid,
            user:user,
            authenticated:true
          })
      }
  
  
      render(){
          console.log(this.state)
          return(
              &lt;Context.Provider value={{   
                   state:this.state
              }}&gt;
                  {this.props.children}
              &lt;/Context.Provider&gt;
          )
      }
  }
  
  const Consumer = Context.Consumer;
  
  export {Provider, Consumer};
  
  </code></pre>
  
  <p><strong>PageComponents/Dashboard</strong></p>
  
  <pre><code>import * as React from 'react';
  import {Consumer} from '../../PageComponents/Context';
  
  
  
  class Dashboard extends React.Component {
    render(){
  
      console.log("Dashboard component loading....")
  
       return(
  
  
          &lt;Consumer&gt;
              {(state)=&gt;{
                  console.log(state)
                  return(
                    &lt;div&gt;
                      &lt;p&gt; Dashboard render&lt;/p&gt;
                    &lt;/div&gt;
                  )
               }}
          &lt;/Consumer&gt;
       )
    }
  }
  
  export default Dashboard
  
  </code></pre>
  
  <p><strong>PageComponents/ProtectedRoute</strong></p>
  
  <pre><code>
  import React from 'react';
  import { Route, Redirect } from 'react-router-dom';
  import { Consumer } from '../PageComponents/Context';
  
  
  const ProtectedRoute = ({ component: Component, ...rest }) =&gt; {
      console.log("Middleware worked!");
  
      return (
  
          &lt;Consumer&gt;
                 {(context)=&gt;{
                  /*________________________BEGIN making sure middleware works and state is referenced */
                    console.log(context);
                    console.log("Middle ware");
                  /*________________________END making sure middleware works and state is referenced */
  
                   console.log(  context.getState().authenticated + " &lt;--- is authenticated from ProtectedRoute. true or false?")
  
                    if(context.state.authenticated){
  
                      return(
  
                          &lt;Route {...rest} render={renderProps =&gt; {
                             console.log(renderProps);
                             return (&lt;Component {...renderProps} /&gt;)
                          }}/&gt;
  
                      )  
  
                    }else{
  
                      return &lt;Redirect to="/"/&gt;
  
                    }
  
                  }}
  
          &lt;/Consumer&gt;
      )
  
  
  };
  
  export default ProtectedRoute;
  
  
  
  
  </code></pre>
  
  <p><strong>services/authentication</strong></p>
  
  <pre><code>import firebase from '../../services/firebase'
  
  
  
  
  const getUser = () =&gt;{
  
      return new Promise((resolve, reject) =&gt; {   // Step 3. Return a promise
  
           //___________________ wrapped async function
  
           firebase.auth().onAuthStateChanged((user)=&gt; {
  
                  if(user){
  
                      resolve(user);   //____This is the returned value of a promise
  
                   }else{
  
                     reject(new Error("Get user error"))
  
                  }
           })
  
         //_____________________END wrapped async function  
  
      });
  
  }
  
  
  export {getUser }
  
  
  </code></pre>