Quiero agregar mi clase personalizada a algunas páginas. por ejemplo
todas las páginas deben ser de esta clase excepción fixed-header estas rutas:
/cart/step-1 /loginesta clase agrega o elimina al elemento del cuerpo.
<body className="bg-gray fixed-header"pero no sé cómo puedo manejar este escenario?
La solución más fácil y rápida. Agregue este código en cada componente donde desee diferentes clases en el <body> .
useEffect( () => { document.querySelector("body").classList.add("bg-gray fixed-header") } );Cree un _document.js y _app.js personalizados en su directorio de páginas.
Una pequeña utilidad para verificar si existe una clase en el cuerpo (para evitar una clase duplicada, gracias a la sugerencia de @juliomalves) :
// ./utils/hasClasses const hasClasses = () => document.body.classList.contains("bg-gray") && document.body.classList.contains("fixed-header"); export default hasClasses; En _document.js , use el accesorio __NEXT_DATA__ para obtener acceso a la página actual, verifique si la página está en sus rutas permitidas y agregue las clases al cuerpo.
import Document, { Html, Head, Main, NextScript } from "next/document"; class MyDocument extends Document { // Add more routes here if you want to use 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;El código anterior siempre se ejecuta en el servidor. Las clases no se agregan al cuerpo en la navegación del lado del cliente.
Para solucionar el problema anterior, use la misma lógica en _app.js en un useEffect , de modo que agregue la clase correcta cuando se represente en el cliente.
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()) { // Don't want the styles in other pages, remove if exists. // Up to your implementation on how you want to handle this. document.body.classList.remove("bg-gray"); document.body.classList.remove("fixed-header"); } }); return <Component {...pageProps} />; } export default MyApp; Esto resuelve el problema donde la navegación del lado del cliente aplica correctamente la clase en la ruta permitida. El código en _document.js se asegura de que cuando una página se procesa en el servidor, se envía en sentido descendente con la clase correcta aplicada para que no provoque un destello de estilos incorrectos en el cliente.