React Routing + Firebase + Redirect + Authentication

Hi,

What is the best approach to check if the user is loggedIn or not and make a redirect based on that.

I am using Firebase for this project.

My app doesn’t require the user to create an account in order to use it, the latter can use the app (search and find products) without being registered.

I tried to use useIonViewWillEnter lifecycle method to redirect the user but no luck. It does not redirect the user.

const Login: React.FC = () => {
	const auth: Auth = useAuth();

	// const user = firebaseAuth.currentUser;
	// if (auth.loggedIn) {
	// 	return <VerifyEmail />;
	// }
	// console.log(user, 'user');

	useIonViewWillEnter(() => {
		console.log(auth, 'auth');
		// console.log(state, 'state');
		if (auth.loggedIn) {
			return <Redirect to='/my/account' />;
		}
	});

	useEffect(() => {
		console.log(auth, 'auth');
	}, [auth]);

	return (
		<IonPage>
			<IonHeader>
				<IonToolbar color='primary'>
					<BackButton />
					<IonTitle>Entrar</IonTitle>
				</IonToolbar>
			</IonHeader>
			<IonContent className='ion-padding'>
				<IonList>
					<LoginForm />
				</IonList>
				<IonItem>
					<IonText>Não tem uma conta?</IonText>
					<IonButton
						fill='clear'
						color='tertiary'
						routerLink='/register'
					>
						Cadastra-se
					</IonButton>
				</IonItem>
			</IonContent>
		</IonPage>
	);
};

I appreciate any help you guys can provide me

Thanks!

Hi,

I’m not the expert in Ionic React but I’ve been facing similar problems recently.

After doing lots of research, the best way is to create an Auth.ts file with Auth Init() function to get the user login status, then use React ContextArea to provide the auth state across the App. Here’s what I have:

Auth.ts

import React, { useContext, useEffect, useState } from "react";
import { auth as firebaseAuth } from "./firebase";

interface Auth {
  loggedIn: Boolean;
  userId?: string;
  userData?:any;
}
interface AuthInit {
  loading: boolean;
  auth?: Auth;
}

export const AuthContext = React.createContext<Auth>({ loggedIn: false });

export function useAuth(): Auth {
  console.log("auth used");
  return useContext(AuthContext);
}

export function useAuthInit(): AuthInit {
  const [authInit, setAuthInit] = useState<AuthInit>({ loading: true });
  useEffect(() => {
    return firebaseAuth.onAuthStateChanged((firebaseUser) => {
      const auth = firebaseUser
        ? { loggedIn: true, userId: firebaseUser.uid, userData: firebaseUser }
        : { loggedIn: false };
      setAuthInit({ loading: false, auth });
    });
  }, []);
  return authInit;
}

** Add auth init at App.tsx to get login status:

import { useAuthInit, AuthContext } from "./auth";

const App: React.FC = () => {
  const { loading, auth } = useAuthInit();
  if (loading) {
    return <IonLoading isOpen translucent />;
  }
  if (auth) {
    console.log("logged in", auth);
  }
return (
    <IonApp>
      <AuthContext.Provider value={auth}>
        <IonReactRouter>
          <Tabs />
        </IonReactRouter>
      </AuthContext.Provider>
    </IonApp>
  );
};

export default App;

login.tsx

  const Login: React.FC = () => {
  const userContext = useContext(AuthContext);
  const [logInEmail, setLogInEmail] = useState("");
  const [logInPassword, setLogInPassword] = useState("");
  const [logInStatus, setLogInStatus] = useState({
    loading: false,
    error: false,
    errorMsg: "",
  });

  if (userContext.loggedIn === true) {
    return <Redirect to="../../user/" />;
  }
  return (
         <IonGrid>
            <IonRow className="ion-justify-content-center">
              <IonCol size="12">
                <IonItem color="" lines="none">
                  <IonLabel>
                    <IonIcon icon={emailIcon} />
                  </IonLabel>
                  <IonInput
                    required
                    autofocus={true}
                    autocorrect="on"
                    type="email"
                    placeholder="Email"
                    value={logInEmail}
                    onIonChange={(event) => setLogInEmail(event.detail.value)}
                  />
                </IonItem>
              </IonCol>
            </IonRow>
            <IonRow className="ion-justify-content-center">
              <IonCol size="12">
                <IonItem color="" lines="none">
                  <IonLabel>
                    <IonIcon icon={keyIcon} />
                  </IonLabel>
                  <IonInput
                    required
                    type="password"
                    placeholder="Password"
                    value={logInPassword}
                    onIonChange={(event) =>
                      setLogInPassword(event.detail.value)
                    }
                  />
                </IonItem>
              </IonCol>
            </IonRow>
            <IonRow className="ion-justify-content-center">
              <IonCol size="12">
                <IonButton type="submit" expand="block">
                  Login
                </IonButton>

                <IonButton
                  type="submit"
                  disabled={!logInEmail || !logInPassword}
                  slot="end"
                  fill="solid"
                >
                  Post
                </IonButton>
              </IonCol>
            </IonRow>
</IonGrid>
  );
};

export default Login;

Also, you could get all firebase user data of the login user anywhere by using this following code:


import { AuthContext } from "../auth";
const userContext = useContext(AuthContext);
...
return(
 console.log(userContext)
)

Hope this helps!

Best,
Oliver

Thank you for your help panjiuzhen but no luck.

The problem is that I am using tabs for navigation and that does not re render the component. It works for the first time but if you navigate away and come back the component is still mounted so it won’t redirect the user again.

I guess I am taking the wrong approach by having the account/login pages in a tab. No luck using ionic life cycle methods either.

Will re think my approach. Maybe adding a hamburger/account icon at the top to handle the account pages.

Thanks!

please checkout this project with addresses authentication with firebase and tabs…

Have you tried redirecting to a route instead of a path?

Change
return <Redirect to="../../user/" />
to
return <Redirect to="/user" />

Or, according to the routes you defined, should be return <Redirect to="/login" />