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.
One way to handle this could be to conditionally use
usePathnameonly when it's available, like: