NextJS Exports error, location not defined

72 views Asked by At

I have NextJS app, where I declare Pages to be client side using "use client" at the top of the file. When I try to build said application, I get errors stating

Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
ReferenceError: location is not defined

and a stack trace pointing somewhere deep inside next.js and it's built files.

Example code in one of those files looks like this:

"use client";

function classNames(...classes: string[]) {
  return classes.filter(Boolean).join(" ");
}

export default function RootTemplate({
  children,
}: {
  children: React.ReactNode;
}) {
  const router = useRouter();
  const pathname = usePathname();
  const [navigation, setNavigation] = useState<any[]>([]);
  const { useSession, signOut } = useContext(AuthContext);

  const userNavigation = [
    { name: "Your profile", click: null, href: "/profile" },
    { name: "Sign out", click: signOut },
  ];

  const [sidebarOpen, setSidebarOpen] = useState(false);
  const { session: data, status } = useSession();
  const username = data?.user?.name;

  useEffect(() => {
    setNavigation([
      {
        name: "Dashboard",
        href: "/",
        icon: HomeIcon,
        current: pathname === "/",
      },
      {
        name: "Users",
        href: "/users",
        icon: UsersIcon,
        current: pathname === "/users",
      },
      {
        name: "Organisation",
        href: "/organisations",
        icon: BuildingOfficeIcon,
        current: pathname === "/organisations",
      },
      {
        name: "Connection",
        href: "/connections",
        icon: LockClosedIcon,
        current: pathname === "/connections",
      },
    ]);
  }, [pathname]);

  if (status === "unauthenticated" && typeof location !== "undefined") {
    if (!(pathname === "/login" || pathname === "/register")) {
      router.push("/login");
      return (
        <>
          <Loading />
        </>
      );
    } else {
      return <>{children}</>;
    }
  }

What I was expecting was that the page would build as an HTML and would not try to prerender on the server as I am using "use client" directive at the top of the file. Meanwhile it seems that nextjs is trying to prerender the page as is, and because usePathname hook from NextJS uses window.location, it fails to build.

I have solved this by checking for location being undefined in the only default state status can have when pre-rendering.

My question is: Why is usePathname using location that is undefined, when it is NextJS hook that should be able to work with this kind of component out of the box, without my ridiculous workaround? Or is my approach to this issue wrong?

1

There are 1 answers

1
J i N On

One way to handle this could be to conditionally use usePathname only when it's available, like:

import { usePathname } from 'your-path-to-usePathname';

let pathname = '/';
 if (typeof window !== 'undefined') {
     pathname = usePathname();
  }
  // Use pathname further in your code