'Firebase onAuthStateChange return undefined when page refresh

Firebase onAuthStateChange return the first result as undefined when I refresh page. Because of that I can not check if user is authenticated or not.

My useAuth hook:

export default function useAuth() {
  const [authUser, setAuthUser] = useState();

  const user = useFirebase();

  useEffect(() => {
    onAuthStateChanged(user.auth, (user) => {
      user ? setAuthUser(user) : setAuthUser(false);
    });
  }, [user]);

  return authUser;
}

When I try to refresh page, first result of user is undefined, end then I get result.

enter image description here

function App() {
  const authUser = useAuth();

  console.log("au", authUser);

  return (
    <div className="App">
      <Routes>
        <Route exact path="/" element={<HomePage />} />
        <Route path="/blogs" element={<BlogsPage />} />
        <Route path="/blog/:id" element={<SingleBlogPage />} />
        <Route path="/contact" element={<ContactPage />} />
        <Route path="/login" element={<AdminLogin />} />
        <Route
          path="/admin"
          element={authUser ? <Dashboard /> : <Navigate to="/vanja-login" />}
        >
          <Route exact path="dashboard" element={<Settings />} />
        </Route>
      </Routes>
      <Footer />
    </div>
  );
}


Solution 1:[1]

The initial authUser state is undefined for the initial render so this is expected behavior. The onAuthStateChanged listener is instantiated at the end of the initial render cycle via the useEffect. If any part of your UI depends on this "indeterminant" authUser state it should handle it accordingly.

Additionally, you should also unsubscribe any auth status listeners when the component unmounts or the user object from firebase updates/changes.

Example:

export default function useAuth() {
  const [authUser, setAuthUser] = useState();

  const user = useFirebase();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(
      user.auth,
      (user) => setAuthUser(user ?? false)
    );

    return unsubscribe;
  }, [user]);

  return authUser;
}

...

const AuthLayout = () => {
  const authUser = useAuth();

  console.log("au", authUser);

  if (authUser === undefined) {
    return null; // or loading spinner, etc...
  }

  return authUser ? <Outlet /> : <Navigate to="/vanja-login" />;
};

...

function App() {
  return (
    <div className="App">
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/blogs" element={<BlogsPage />} />
        <Route path="/blog/:id" element={<SingleBlogPage />} />
        <Route path="/contact" element={<ContactPage />} />
        <Route path="/login" element={<AdminLogin />} />
        <Route path="/admin" element={<AuthLayout />}>
          <Route index element={<Dashboard />} />
          <Route path="dashboard" element={<Settings />} />
        </Route>
      </Routes>
      <Footer />
    </div>
  );
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Drew Reese