Search code examples
reactjsgoogle-cloud-firestoreroutesnavbar

React useAuth and Routes with Firestore


I'm noticing in the firestore usage console that the App is consuming more reads than I was expecting on the first load (I was expecting 1 and it is consuming 9) something is rendering more times than excpected. I've tried using console.logs whenever I access firestore but doesn't seem to bring any help.

I'm new to React and there is obviously something I'm doing wrong, I've read plenty of posts and the docs but I'm struggling to understand what I'm doing wrong.

Any advice is welcome

index.js:

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <StrictMode>
    <BrowserRouter>        
      <AuthProvider>
        <App />        
      </AuthProvider>
    </BrowserRouter>
  </StrictMode>
)

userContext.js:

const AuthContext = createContext()
    
    async function logIn(email, password) { 
      await signInWithEmailAndPassword(auth, email, password)
    }
    
    async function logOut() {
      await signOut(auth)  
    }
    
    async function register(email, password) {
      return createUserWithEmailAndPassword(auth, email, password)
    }
    
    export function AuthProvider({ children }) {    
      const [userData, setUserData] = useState(null)
        
      useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, async (authUser) => {
          if (authUser) {
            try {             
              const docRef = doc(db, 'USERS', authUser.uid)
              const docSnap = await getDoc(docRef)
              const data = docSnap.data()    
              setUserData(data)          
            } catch (error) {
              console.error(error)
            }
          } else {
            setUserData(null)
          }
        })
    
        return () => unsubscribe()
      }, [])
    
      const authContextValue = {    
        userData,        
        logIn,
        logOut,
        register,
      }
    
      return (
        <AuthContext.Provider value={authContextValue}>
          {children}
        </AuthContext.Provider>
      )
    }



    export function useAuth() {
      const context = useContext(AuthContext)
    
      if (!context) {
        throw new Error('No context provider')
      }
    
      return context
    }

App.js

export default function App() {   
  const { userData } = useAuth()

  return (
    <>    
      {userData ? (
      <Routes>
        <Route path="/" 
          element={
            <>
              <AppNavbar /> 
              <Outlet />
            </>
          }>
          
          <Route path="page1" element={<Page1/>} />
          <Route path="page2" element={<Page2/>} />
        </Route>
      </Routes>
      
      ) : (      
        <Routes>
          <Route path="login" element={<Login />} />
          <Route path="register" element={<Register />} />          
        </Routes>
      
      )}

  </>
  )
}

Solution

  • Remove the <StrictMode /> in your root rendering. And move AuthProvider higher in the component tree for consistent authentication state.

    Note : Removing Strict Mode is a debugging step to isolate issues, not a recommended solution. Strict Mode highlights potential problems but doesn't inherently cause excessive renders. Instead, focus on optimizing code, checking dependencies in useEffect, and debugging with console logs to address the root cause of unexpected renders.

    const root = ReactDOM.createRoot(document.getElementById('root'))
    root.render(
      // <StrictMode> : Remove React Strict Mode
      <AuthProvider> {/* Moved the AuthProvider to the top of the tree */}
        <BrowserRouter>
          <App />
        </BrowserRouter >
      </AuthProvider>
      // </StrictMode>
    )