I am using Next.JS for my SPA website in React.
My Layout includes , sidebar and footer.
My problem is that when I have useEffect(() => { //SOMETHING }, []); in my Layout component it gets called every time I change page with Next.js's <Link> or router.push(path).
From my research, everything on page gets rerendered.
This should not be hapenning. Components outside of Layout should just receive update and not complete rerender. Only stuff inside Layout should get rerendered (same way as React Router) works.
What is causing this? Is it fixable or is it Next.js's by design.
Minimal example: https://codesandbox.io/s/nextjs-ebdz5
In the minimal example for the Layout component you are creating a new random value each time the route/path/view changes and rerendered. This is an unintentional side-effect and is not an accurate method at all for determining what is being mounted/remounted or rendered/rerendered as it's not using any of the React component lifecycle.
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>
);
}
Click on different page and observe that random number changes which means that layout component gets rerendered and reinitialized every time.
This is a very false assumption/conclusion.
If at a minimum you place the random value into a React state
const [random] = useState(Math.random());
you'll clearly see it remains constant and never changes no matter how many times you navigate between "/" and "/about" links/pages. In other words, the state persists exactly as the docs claim.
In fact, if you take it a step further and also use a mounting useEffect hook
useEffect(() => {
console.log("Layout MOUNTED", { random });
}, []);
you'll see it only ever logs once with the random state value and never changes or logs again.
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>
);
}