title: Persist Google Auth Info with React, React-Router
body: <p>I was hoping to persist authentication across multiple pages, but with every page load, the credentials are reloaded rather than seen already to be retrieved. It could just be that I am mistaking how this would work, but I would be happy to hear best practices around this.</p>
  <p>I am using Firebase/Google authentication, and</p>
  <p>want to use their <code>onAuthStateChanged</code> function, storing the credential information between the different pages. In my mind, this would be considered the same &quot;session&quot;, though I am coming from a mobile background and might be misunderstanding web-concepts.</p>
  <p><code>onAuthStateChanged</code> is being hit every time I route to a new page which isn't the biggest of deals, but I was hoping also to hold onto other user information that I fetch using the information Firebase returns. Because of this, on every page load, <code>onAuthStateChanged</code> is triggered, and nothing is persisting, and so I need to re-retrieve the other user information that I need.</p>
  <p>I'll lay out the code, and then clarify the question further afterwards.</p>
  <h1>1. Code Setup</h1>
  <p>First off, I have my App class itself:</p>
  <pre><code>import React, { useEffect } from 'react'
  import Navigation from './components/Navbar'
  import Routes from './Routes'
  import { AuthProvider } from './services/contexts/AuthContext'
  
  function App() {
    return (
      &lt;AuthProvider&gt;
        &lt;Navigation /&gt;
        &lt;Routes /&gt;
      &lt;/AuthProvider&gt;
    )
  }
  
  export default App
  </code></pre>
  <p>Routes is pretty straight forward. For brevity, it resembles this:</p>
  <pre><code>import React, { Component } from 'react'
  import { Router, Switch, Route } from 'react-router-dom'
  
  import Home from './pages/Home'
  import history from './history'
  import Pricing from './pages/Pricing'
  import PrivateRoute from './PrivateRoute'
  import Account from './pages/Account'
  
  export default class Routes extends Component {
    render() {
      return (
        &lt;Router history={history}&gt;
          &lt;Switch&gt;
            &lt;Route path=&quot;/&quot; exact component={Home} /&gt;
            &lt;Route path=&quot;/pricing&quot; component={Pricing} /&gt;
            &lt;PrivateRoute path=&quot;/account&quot; component={Account} /&gt;
          &lt;/Switch&gt;
        &lt;/Router&gt;
      )
    }
  }
  </code></pre>
  <p>And Navigation is like:</p>
  <pre><code>import React from 'react'
  import { Navbar, Nav } from 'react-bootstrap'
  import { withRouter } from 'react-router-dom'
  
  import { useAuth } from '../services/contexts/AuthContext'
  
  const Navigation = (props) =&gt; {
    const { currentUser } = useAuth()
  
    // console.log(props)
    return (
      &lt;Navbar className=&quot;navbarColor&quot; variant=&quot;dark&quot;&gt;
        &lt;Navbar.Toggle aria-controls=&quot;basic-navbar-nav&quot; /&gt;
        &lt;Navbar.Collapse id=&quot;basic-navbar-nav&quot;&gt;
          &lt;Nav className=&quot;mr-auto&quot;&gt;
            &lt;Nav.Link href=&quot;/&quot;&gt;Home&lt;/Nav.Link&gt;
            {!currentUser &amp;&amp; &lt;Nav.Link href=&quot;/pricing&quot;&gt;Pricing&lt;/Nav.Link&gt;}
            {currentUser &amp;&amp; &lt;Nav.Link href=&quot;/account&quot;&gt;Account&lt;/Nav.Link&gt;}
          &lt;/Nav&gt;
        &lt;/Navbar.Collapse&gt;
      &lt;/Navbar&gt;
    )
  }
  
  export default withRouter(Navigation)
  </code></pre>
  <p>Finally, authorization-handling looks like this:</p>
  <pre><code>import React, { useContext, useEffect, useState } from 'react'
  import { auth } from '../Authentication/firebase'
  
  const AuthContext = React.createContext()
  
  export function useAuth() {
    return useContext(AuthContext)
  }
  
  export const AuthProvider = ({ children }) =&gt; {
    const [currentUser, setCurrentUser] = useState()
    const [loading, setLoading] = useState(true)
  
    useEffect(() =&gt; {
      const unsubscribe = auth.onAuthStateChanged(async (user) =&gt; {
        console.log('setting up user')
        setCurrentUser(user)
        // Fetch other user information, like subscription, from my own database
        setLoading(false)
      })
  
      return unsubscribe
    }, [])
  
    const value = {
      currentUser
    }
    return (
      &lt;AuthContext.Provider value={value}&gt;
        {!loading &amp;&amp; children}
      &lt;/AuthContext.Provider&gt;
    )
  }
  </code></pre>
  <h1>2. Further Question Clarification</h1>
  <p>I had put the <code>onAuthStateChanged</code> within <code>useEffect</code>, and wrapped the router within the <code>AuthContext</code>, which made me think that any routing would use the same context, and so <code>useEffect</code> (with no parameters) would not be called again. It's not that <code>useEffect</code> is triggered multiple times, but rather than it seems like the whole component is recreated, making me think that perhaps the issue has to do with me incorrectly doing something for react not to have to re-render absolutely everything.</p>
  <p>I hope that is clear; let me know if I need to clarify anything or provide any further information.</p>
  <h2>Update</h2>
  <p>I realized that partly the reason why it wasn't &quot;loading&quot; the way I wanted it to is that the way I had the auth setup, no child view was returned until <code>loading</code> was marked to true. At least visually I improved this by adding a <code>{loading &amp;&amp; &lt;Loading/&gt;}</code> so that certain shared elements (like the nav bar) could load while waiting on the auth process.</p>
  <p>This isn't the answer to my question per se so it would still be nice to hear how people handle storing auth in the best way.</p>