I am trying to follow the persistent layout examples as presented on the official docs and Adam Wathan's article here.
This is what I know so far:
Based on the above, I would say that persistent layout works because the layout used in _app.js is provided the page as its prop (children). Since layout's own state doesn't change, layout shouldn't get re-rendered. However, that is not what I am noticing, and hence this long winded question.
Just so I am clear, when i say re-render, I am talking about React recreating the virtual dom for the component rather than repainting the html dom. My issues are with the former and not the later.
What I am seeing is that every time I click on the "Profile" link (even if I am already on the same page):
I thought that a persistent layout meant that it wouldn't be re-evaluated all the time? The printing of console logs indicates that the component is being re-evaluated every time. I know React.memo would avoid this entirely, but then what exactly is "persistence" about this? What am i missing or failing to understand about persistent layouts in this case?
What I have looks like this:
/pages/profile.js (and similarly /pages/anotherPage.js)
function sampleProfilePage (props) = {
return (
<div>I am on profile page</div>
);
}
export default sampleProfilePage
_app.js
function MyApp({Component, pageProps}) {
return (
<SimpleLayout>
<Component {...pageProps} />
<SimpleLayout />
);
}
SimpleLayout.js
function SimpleLayout ({children}) {
return (
<>
{console.log("simpleLayout re-rendered")}
<SimpleTopBar />
<main>{children}</main>
</>
);
}
export default SimpleLayout;
SimpleTopbar.js NOTE: css can be ignored. Its present in .module.css file.
function SimpleTopBar () {
return (
<div className={classes.container}>
{console.log("SimpleTopBar re-rendered")}
<Link href="/profile">Profile</Link>
<IconCircle />
<SearchBar />
<IconSquare />
<Link href="/anotherPage">Another Page</Link>
</div>
);
}
export default SimpleTopBar;
IconCircle (and similarly IconSquare) NOTE: ignore css again. Also, I recently became aware that defaultProps are deprecated. I am in the process of updating/writing inline default values.
export function IconCircle (props) {
return (
<svg xmlns="http://www.w3.org/2000/svg"
className={props.name}
... rest of svg data ...
</svg>
);
}
IconCircle.defaultProps = {
name: classes.iconCircle
}
SearchBar.js NOTE: this is taken straight from Adam's code in order to try and compare what I was seeing.
function SearchBar (props) {
return (
<div className="mt-2">
{console.log("Search bar rendered")}
<input className="block w-full border border-gray-300 rounded-lg bg-gray-100 px-3 py-2 leading-tight focus:outline-none focus:border-gray-600 focus:bg-white"
placeholder="Search..."
/>
</div>
);
}
export default SearchBar;
Disclaimers: I am a backend engineer and just starting to learn React and Nextjs. Its is highly possible that my design and understanding is limited or not exactly what one might expect in the industry/professionally. So, if there are some general practices or commonly known knowledge, please do not assume that I am following that or aware of it. Its part of the reason why I pasted entire functions. I am still reading up on various pages/questions and trying various things to rule things out, or understand better what is being shown/told to me.
Thank you in advance for the patience to read this question, and sorry for its length.
You have a pretty good understanding of what's happening.
All pages in Next.js depend on _app - it rerenders because of pageProps or more likely Component prop changes - forcing the children to rerender.
The layouts will 'persist' between pages - the children should rerender on a route change but, components that are still on the page should keep their state.
i.e. a search input in the layout should keep its search term on route changes to another page with the same layout.
The only way not to rerender during route change is to use shallow routing . But it doesn't really route - it just allows you to add query params to the current route (can't change pages or it will use standard routing).
As you mentioned, you can use memo on some of your components to prevent rerendering, but only use it when you know you need it and use it wisley.
Lastly, rerendering is also part of React and virtual DOM manipulation, I wouldn't worry about it too much until it becomes a problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With