Estoy usando Next.JS para mi sitio web SPA en React.
Mi diseño incluye, barra lateral y pie de página.
Mi problema es que cuando tengo useEffect(() => { //SOMETHING }, []); en mi componente Layout se llama cada vez que cambio de página con <Link> o router.push(path) de Next.js.
De mi investigación, todo en la página se vuelve a representar.
Esto no debería estar pasando. Los componentes fuera de Layout solo deben recibir una actualización y no una nueva representación completa. Solo las cosas dentro de Layout deben volver a renderizarse (de la misma manera que React Router) funciona.
¿Qué está causando esto? ¿Se puede reparar o es de Next.js por diseño?
Ejemplo mínimo: https://codesandbox.io/s/nextjs-ebdz5
En el ejemplo mínimo para el componente Layout , está creando un nuevo valor random cada vez que la ruta/ruta/vista cambia y se vuelve a representar. Este es un efecto secundario no intencional y no es un método preciso en absoluto para determinar qué se está montando/remontando o renderizando/volviendo a renderizar, ya que no utiliza ninguno de los componentes del ciclo de vida de React.
export default function Layout({ children }) { const random = Math.random(); // <-- side-effect!! return ( <div> <div style={{ backgroundColor: "red" }}>{random}</div> <div> <Link href="/about">About</Link> <Link href="/">Index</Link> </div> <main>{children}</main> <footer> Click on different page and observe that random number changs which means that layout component gets rerendered and reinitialized everytime. </footer> </div> ); }Haga clic en una página diferente y observe que el número aleatorio cambia, lo que significa que el componente de diseño se vuelve a renderizar y reinicializar cada vez.
Esta es una suposición/conclusión muy falsa.
Si, como mínimo, coloca el valor random en un estado Reaccionar
const [random] = useState(Math.random()); verá claramente que permanece constante y nunca cambia, sin importar cuántas veces navegue entre los enlaces/páginas "/" y "/about" . En otras palabras, el estado persiste exactamente como afirman los documentos.
De hecho, si vas un paso más allá y además usas un gancho de montaje useEffect
useEffect(() => { console.log("Layout MOUNTED", { random }); }, []); verá que solo se registra una vez con el valor de estado random y nunca cambia ni se registra de nuevo.
export default function Layout({ children }) { const [random] = useState(Math.random()); useEffect(() => { console.log("Layout MOUNTED", { random }); }, []); return ( <div> <div style={{ backgroundColor: "red" }}>{random}</div> <div> <Link href="/about">About</Link> <Link href="/">Index</Link> </div> <main>{children}</main> <footer> Click on different page and observe that random number changs which means that layout component gets rerendered and reinitialized everytime. </footer> </div> ); }