I do have a verify page and status check page. I want to be able to check the user who logged in if his/her status is a boolean(string) in the cloud firestore. However, whenever the user is successfully logged in, it goes to the ("/")
or the dashboard of the page wherein it should be only seen by users who are authenticated and have both true fields in isEmailVerified
and isVerified
in the cloud firestore.
route.js
export function withProtected(Component) {
return function withProtected(props) {
const auth = useAuth();
const router = useRouter();
var isEmailVerified;
var isAdminVerified;
async function readData() {
// getUuid is from useAuth() in my AuthService.js
const docRef = doc(db, "admins", auth.getUuid);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
isEmailVerified = docSnap.data()["isEmailVerified"];
isAdminVerified = docSnap.data()["isVerified"];
if (auth.getUuid && isEmailVerified == "false") {
console.log("Verify Email Page Pushed!!!!");
Router.push("/components/VerifyEmailPage");
return <h1>GO TO VERIFY EMAIL PAGE</h1>;
} else if (auth.getUuid && isAdminVerified == "false") {
console.log("pushed!");
Router.push("/components/AdminRequestStatus");
return <h1>GO TO ADMIN STATUS CHECKER PAGE</h1>;
}
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}
useEffect(() => {
readData();
}, []);
return <Component auth={auth} {...props} />;
};
}
and here is the import of my route.js file
import Router, { useRouter, asPath } from "next/router";
import React, { useEffect, useState } from "react";
import { useAuth } from "../utilities/AuthService";
import { db } from "../utilities/firebase-config";
import { doc, getDoc, onSnapshot, query } from "firebase/firestore";
import AdminRequestStatus from "./AdminRequestStatus";
import VerifyEmailPage from "./VerifyEmailPage";
Here is the VerifyPage where should be redirected when the value of isEmaiVerified
is still false, I wrapped the Page of the function that I created withProtected
import React from "react";
import Head from "next/head";
import { withProtected } from "./route";
import Header from "./Header";
function VerifyEmailPage() {
return (
<div>
<Head>
<title>Verify Email Page</title>
</Head>
<Header></Header>
</div>
);
}
// I wrapped the VerifyEmailPage with the withProtected function
// that I created..
export default withProtected(VerifyEmailPage);
I am relatively new with react.js and next.js so your insights and ideas would be appreciated. Thank you.
Instead of solving for flashing while redirecting you can introduce a loading state with the initial state as true, and change this state to false, whenever you finish loading the data from the firestore query.
Here’s how you could do it:
import { useState, useEffect } from "react";
import Router from "next/router";
import { useAuth } from "../utilities/AuthService";
export function withProtected(Component) {
return function withProtected(props) {
const auth = useAuth();
const [loading, setLoading] = useState(true);
async function readData() {
const docRef = doc(db, "admins", auth.getUuid);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const isEmailVerified = docSnap.data()["isEmailVerified"];
const isAdminVerified = docSnap.data()["isVerified"];
if (auth.getUuid && isEmailVerified === false) {
Router.push("/components/VerifyEmailPage");
} else if (auth.getUuid && isAdminVerified === false) {
Router.push("/components/AdminRequestStatus");
}
} else {
console.log("No such document!");
}
setLoading(false);
}
useEffect(() => {
readData();
}, []);
if (loading) {
return <h1>Loading...</h1>; //you can also create loading component
}
return <Component auth={auth} {...props} />;
};
}
You can also use some Spinning Loading components to make it more clean.