'Error: React Hook "useDocumentOnce" is called conditionally. React Hooks must be called in the exact same order in every component render

I was making an app using NextJS, TailwindCSS, Firebase and It is working 100% correctly on local host but on deploying on Vercel, I get the following error :

15:18 Error: React Hook "useRouter" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks 17:39 Error: React Hook "useDocumentOnce" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks

enter image description here

I am not able to understand why I get this error when deploying my app to Vercel.Maybe it's something related to redirect link in google API console

Here's my [id].js file :

import TextEditor from "../../components/TextEditor";
import Button from "@material-tailwind/react/Button";
import Icon from "@material-tailwind/react/Icon";
import { useRouter } from "next/dist/client/router";
import { db } from "../../firebase";
import { useDocumentOnce } from "react-firebase-hooks/firestore";
import { getSession, signOut, useSession } from "next-auth/client";
import Login from "../../components/Login";

function Doc() {
  const [session, loading] = useSession();
  console.log(session);
  if (!session) return <Login />;

  const router = useRouter();
  const { id } = router.query;
  const [snapshot, loadingSnapshot] = useDocumentOnce(
    db.collection("userDocs").doc(session.user.email).collection("docs").doc(id)
  );

  // Redirect if user tries to access a URL they do not have access to...
  if (!loadingSnapshot && !snapshot?.data()?.fileName) {
    // Filename will not be present if the user doesnt have access...
    router.replace("/");
  }

  return (
    <div>
      <header className="flex justify-between items-center p-3 pb-1">
        <span onClick={() => router.push("/")} className="cursor-pointer">
          <Icon name="description" size="5xl" color="blue" />
        </span>
        <div className="flex-grow px-2">
          <h2 className="text-lg text-left">{snapshot?.data()?.fileName}</h2>
          <div className="flex items-center text-sm -ml-1 h-8 text-gray-600 space-x-1">
            <p className="option">File</p>
            <p className="option">Edit</p>
            <p className="option">View</p>
            <p className="option">Insert</p>
            <p className="option">Format</p>
            <p className="option">Tools</p>
          </div>
        </div>

        <Button
          color="lightBlue"
          buttonType="filled"
          size="regular"
          className="hidden md:!inline-flex h-10"
          rounded={false}
          block={false}
          iconOnly={false}
          ripple="light"
        >
          <Icon name="people" size="md" /> SHARE
        </Button>

        <img
          onClick={signOut}
          className="cursor-pointer h-10 w-10 rounded-full ml-2"
          src={session.user.image}
          alt=""
        />
      </header>
      <TextEditor />
    </div>
  );
}

export default Doc;

export async function getServerSideProps(context) {
  const session = await getSession(context);

  return {
    props: {
      session,
    },
  };
}


Solution 1:[1]

You have early return before calling useDocumentOnce on line

if (!session) return <Login />

Which is not good as the error says. You should make sure that you always render the same amount of hooks on each render. In your case you are calling 3 hooks. But if session is not defined you only render 1 hook. That is the problem you have to resolve.

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