Alex Ironside
Alex Ironside

Reputation: 5039

firebase.auth().onAuthStateChanged looping infinitely

I have this code:

function App() {
  const { setUser } = useContext(UserContext);
  firebase.auth().onAuthStateChanged((user) => {
    console.log("test");
    if (user) {
      console.log("user");
      setUser({ id: user.uid, email: "" });
    } else {
      console.log("null");
      setUser(null);
    }
  });

  return (
    <Container>
      <Router />
    </Container>
  );
}

userContext:

const initialState = {
  email: null,
  id: null,
};

export interface IUserContext {
  user: IUser | null;
  setUser: React.Dispatch<IUser | null>;
}

export const UserContext = createContext<IUserContext>({
  user: initialState,
  setUser: () => {},
});

interface IUserContextProvider {
  children: JSX.Element;
}
export function UserContextProvider({ children }: IUserContextProvider) {
  const [user, setUser] = useState<IUser | null>(initialState);
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

I am trying to set a user object on log in, or log out. The problem is this keeps looping infinitely. How do I stop this from happening? I essentially just want to know when someone is logged in, or logged out.

Upvotes: 1

Views: 552

Answers (1)

Lakshya Thakur
Lakshya Thakur

Reputation: 8308

This can be the responsibility of your Provider itself and run inside it's useEffect like so :-


export function UserContextProvider({ children }: IUserContextProvider) {
  const [user, setUser] = useState<IUser | null>(initialState);

useEffect(()=>{
   const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
    console.log("test");
    if (user) {
      console.log("user");
      setUser({ id: user.uid, email: "" });
    } else {
      console.log("null");
      setUser(null);
    }
  });
 return unsubscribe;
},[])

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

The onAuthStateChanged only needs to be registered one-time and so [] dependency array useEffect is the right place for it. The unsubscribe will only work when this component unmounts which won't happen for you unless you exit the website.

Upvotes: 2

Related Questions