Next.js Discord

Discord Forum

Syncing server and client components

Unanswered
Montezuma Quail posted this in #help-forum
Open in Discord
Montezuma QuailOP
I have a navbar server component and a breadcrumb client component. When I login the navbar loads first and then the breadcrumb component delays and then loads. When I try to make the breadcrumb component and server component and get the path it doesn’t work properly. What’s the best way to accomplish getting these to be in sync?

8 Replies

American black bear
to fix this you need to make your breadcrumb a server component. to achieve this you can either manually specify the breadcrumb data for each page or use middleware or similar to add a custom header containing the current pathname which you will be able to access on server.
approach 1.

// on each page manually insert breadcrumb data
// app/services/development/page.tsx

export function ServicesDevelopmentPage() {
  return (
    <Breadcrumbs data={["home", "services", "development"]} />
  )
}
however if you want your breadcrumbs to be automatically generated you can also use the middelware approach.

1. create middleware.ts in /src folder NOT app as it will not work lol
2. set a custom pathname header which you will be able to access in your server components
3. access the header using a server action or server function

// /src/middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  // add pathname header
  const headers = new Headers(request.headers);
  headers.set("x-current-path", request.nextUrl.pathname);
  return NextResponse.next({ headers });
}

export const config = {
  matcher: [
    "/((?!api|_next/static|_next/image|favicon.ico).*)",
  ],
};
You can then get the header if your breadcrumb is a server component by using next/headers.

import {headers as headersPromise} from "next/headers"

export function getPathname() {
  const headers = await headersPromise()

  const pathname = headers.get("x-current-path")

  return pathname ?? "/"
}
Also be careful when using this approach as it will make your entire route dynamically rendered. To fix this you can make getPathname a server action by adding "use server" to the top of the file.
This is if you want them to load in sync, but keep in mind that you are nitpicking here and you could just make it so a skeleton is showing for breadcrumbs while they are loading. Not everything needs to be rendered on the server and displayed instantly as the page loads.
Montezuma QuailOP
To use the skeleton loading approach though wouldn’t it have to be a server component ?
American black bear
no you can conditionally render a skeleton while pathname value is not defined or empty string