nextjs layout only running on the first render
Answered
Sardinian Shepherd Dog posted this in #help-forum
Sardinian Shepherd DogOP
Hello,
I have a nextjs layout using the app directory and im having an issue where the layout is only rendered on the initial page load. I have a loading state which is being used in a
I have a nextjs layout using the app directory and im having an issue where the layout is only rendered on the initial page load. I have a loading state which is being used in a
<Suspence>
boundary, and it works fine.. but only for the first page render. If I refresh the page using f5, it works fine, every time. However, if I use my navigation bar using nextJs <Link>
component, the layout isn't rerendered and the loading state is never output onto the screen. I can verify that the layout is never called by adding some console.logs
inside of it. Is this something to do with nextjs caching the layout? If so, how can I fix this?export default async function Layout({ children, params }: Props) {
const session = await getServerSession(authOptions);
return (
<SidebarProvider>
<Suspense fallback={<LoadingOverlay />}>
<main className="w-full p-4">{children}</main>
</Suspense>
</SidebarProvider>
);
}
12 Replies
Asian black bear
It is by design. Layouts don't rerender if not necessary and if you have a layout that wraps something and you navigate under that path it doesn't have to rerender.
For instance you can see the root layout for a home page and navigating to to dashboard which has the same parent root layout means that the root layout doesn't get rerendered, it will be reused.
Only the new child layouts and pages get rendered and slotted in.
Sardinian Shepherd DogOP
Ohh okay, that makes sense, thank you.
Because of this how would I display the loading state for page renders after the inital load?
When redirecting a user to another page, but still under the same layout the page will fetch content which can take x number of seconds, so i was using a suspense component inside of the layout so I can reuse it for all pages under my (dashboard) directory.
(dashboard)/layout.tsx
(dashboard)/dashboard/page.tsx
in my page.tsx, I can't add a suspense because the data fetching is happening above it, so it doesn't reach the block to tell the client that something is still being fetched
Because of this how would I display the loading state for page renders after the inital load?
When redirecting a user to another page, but still under the same layout the page will fetch content which can take x number of seconds, so i was using a suspense component inside of the layout so I can reuse it for all pages under my (dashboard) directory.
(dashboard)/layout.tsx
export default async function Layout({ children, params }: Props) {
const session = await getServerSession(authOptions);
return (
<SidebarProvider>
<Suspense fallback={<LoadingOverlay />}>
<main className="w-full p-4">{children}</main>
</Suspense>
</SidebarProvider>
);
}
(dashboard)/dashboard/page.tsx
export default async function Overview({ params }: Props) {
await new Promise((resolve) => setTimeout(resolve, 1000)); // fake delay for simplicity
return (
<HydrateClient>
<Modules />
</HydrateClient>
);
}
in my page.tsx, I can't add a suspense because the data fetching is happening above it, so it doesn't reach the block to tell the client that something is still being fetched
Asian black bear
You use the loading.tsx file for that.
Answer
Asian black bear
It will be automatically slotted into the place where the page will end up being.
Using Suspense manually isn't a common usecase
Because Next will add the boundaries itself when it see you're using loading.tsx components
Which is the more idiomatic approach.
Sardinian Shepherd DogOP
ohhh okay thank you, ill have a look into switching to this now 🙂
Thank you very much 🙂
Asian black bear
You're welcome.