Published on November 28th, 2024
If you tried to use state or onclick or any other kind of interactivity in a component imported by the _document file in the nextjs page router like a navbar with onclick property or anyother kind of client-side interactivity in it will fail to work, but it won't throw any kind of error either on the client side nor on the server. I ran into the same error while trying to implement a click dropdown in the globally shared navigation Bar and wasted 3 days trying to fix it.
All you have to do is move the import and declaration of the code that has client side interactivity or state in it from the _document
file and put it in the _app.tsx/jsx/js
file in the src
dir
Former code: _document.tsx:
import TopNav from "@/components/TopNav";
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head/>
<body className="">
<TopNav /> //TopNav has client side code
<Main />
<NextScript />
</body>
</Html>
);
}
_app.tsx:
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
New Codes: _document.tsx:
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head/>
<body className="">
<Main />
<NextScript />
</body>
</Html>
);
}
_app.tsx:
import "@/styles/globals.css";
import TopNav from "@/components/TopNav";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return <><TopNav/><Component {...pageProps} /></>;
}
_document is only rendered on the server, but __app renders both on the server and client which therefore allows you to add clients side interactivity to your code and it is also shared between all pages.
Another way to fix it is to move you entire codebase to the newer app routing system which i personally hate
The reason this issue occurs is because the _document component renders only on the server then pass compiled html to the client which in other words disables any kind of programmed interactivity you want on the client side and all you need to do is move the code that needs client side interactivity into the _app file which is also shared with all pages