Start by creating your own custom _document.js
and _app.js
files within the pages directory.
Here's a handy utility function to check for classes on the body element (to prevent duplicate classes, inspired by @juliomalves):
// ./utils/hasClasses
const hasClasses = () =>
document.body.classList.contains("bg-gray") &&
document.body.classList.contains("fixed-header");
export default hasClasses;
Implementing Server-Side Rendering
In the _document.js
file, utilize the __NEXT_DATA__
prop to access the current page,
verify if the page is in your approved routes, and add appropriate classes to the body element.
import Document, { Html, Head, Main, NextScript } from "next/document";
class MyDocument extends Document {
// Add more routes here if you wish to apply the same classes
allowedRoutes = ["/login", "/cart/step-1"];
getColor() {
const { page } = this.props?.__NEXT_DATA__;
if (this.allowedRoutes.includes(page))
return "bg-gray fixed-header";
return "";
}
render() {
return (
<Html>
<Head />
<body className={this.getColor()}>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
This code will execute exclusively on the server side. The classes won't be added to the body during client-side navigation.
Client-Side Rendering Solution
To address the aforementioned issue, apply the same logic found in _app.js
within a useEffect
hook, ensuring that the appropriate class is added during client-side rendering.
import { useEffect } from "react";
import { useRouter } from "next/router";
import "../styles.css";
import hasClasses from "./utils/hasClasses";
function MyApp({ Component, pageProps }) {
const { pathname: page } = useRouter();
const allowedRoutes = ["/login", "/cart/step-1"];
useEffect(() => {
if (!hasClasses() && allowedRoutes.includes(page))
document.body.className += "bg-gray fixed-header";
else if (hasClasses()) {
// Eliminate styles on other pages to prevent conflicts.
// Determine how to handle this based on your needs.
document.body.classList.remove("bg-gray");
document.body.classList.remove("fixed-header");
}
});
return <Component {...pageProps} />;
}
export default MyApp;
This approach ensures proper application of classes during client-side navigation on permitted routes. The code within _document.js
guarantees that pages rendered on the server are transmitted with correct styling to prevent any visual glitches on the client side.