skip to Main Content

My webpage requires to reload every time to update user state.
As to the problem, in the handleLogin func, the page should be redirected to homepage (‘/’) and refresh itself, so that the user state is updated, due to AuthContextProvider Component checking onAuthStateChanged. However, it can only either reload the page, or redirect to homepage (which I manually need to refresh). So please help me with some ideas to this one.

I am thinking of doing global.this to add a boolean which handleLogin can access locally How to declare a global variable in React?.
And since most of these are client components, so far only router.push can redirect between pages.

src/app/login/page.jsx

'use client';

import Link from "next/link";
import "../../components/auth";

import { useState } from "react";
import { auth } from "../../components/auth";
import { signInWithEmailAndPassword } from "firebase/auth";
import { useRouter } from "next/navigation";
import { redirect } from "next/navigation";

//SOME CONDITIONALS VALID_EMAIL AND VALID_PASSWORD 

export default function loginPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const router = useRouter();
  //*EVENT
  const handleLogin = async (e) => {
    e.preventDefault();
    if (valid_email(email) && valid_password(password)) {
      signInWithEmailAndPassword(auth, email, password)
        .then((res) => {
          console.log({ res });
          router.push('/'); //WORKAROUND?
          document.reload(); //WORKAROUND?
        })
        .catch((e) => console.error(e));
    }
  }

   // RETURN SOME RENDERING

src/components/authContext.jsx

'use client'
import React from 'react';
import { onAuthStateChanged} from 'firebase/auth';
import { auth } from "../components/auth"
import { useRouter } from 'next/navigation';

export const AuthContext = React.createContext({});

export const useAuthContext = () => React.useContext(AuthContext);

const AuthContextProvider = ({
    children,
}) => {
    const [user, setUser] = React.useState(null);
    const [loading, setLoading] = React.useState(true);
    const [redirect, setRedirect] = React.useState(false);
    const router = useRouter();

    React.useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, (user) => {
            if (user) {
                setUser(user);
                if (redirect) location.reload();

            } else {
                setUser(null);
                if (redirect) location.reload();
            }
            
            setRedirect(false);
            setLoading(false);
        });

        return () => unsubscribe();
    }, []);

    return (
        <AuthContext.Provider value={{ user }}>
            {loading ? <div>Loading...</div> : children}
        </AuthContext.Provider>
    );
};

export default AuthContextProvider;

2

Answers


  1. Using router.push(redirectUrl ?? '/'); is a common pattern for this, especially if a user has been directed to the login page after trying to access an auth-protected route, they can then be redirected back to the page they were originally browsing.

    Login or Signup to reply.
  2. First of all move the handleLogin to the AuthContext and use from there only by either useContext or you can create a hook useAuth for that.
    if the error persist then use useEffect to push to "/" after the state changes not in the handleLogin func.

    Here’s an example

    const [user, setUser] = useState();
    const [isLoading, setIsLoading] = useState(true);
      
    useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, (user) => {
          setUser(user);
          setIsLoading(false);
        });
        return () => unsubscribe();
      }, []);
      
      useEffect(() => {
        if (!user && !isLoading) {
          router.push("/");
        }
      }, [user, router, isLoading]);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search