Handling Headers and Parameters In NextJS 15
Next.js 15 introduced some changes to how we handle parameters and headers. We'll explore these changes and learn how to implement them using dynamicIO
.
Headers
First, let's take a look at headers. We want to get the headers from the incoming request and avoid caching them. To do this in Next.js 15 with dynamicIO
, we need to wrap our code in a suspense boundary. This is different from Next.js 15 without dynamicIO
, where you wouldn't need to add a suspense boundary.
Here's an example of how to wrap your code in a suspense boundary:
async function Headers() {
const out = await headers();
const keys = Object.keys((out as unknown as { headers: object }).headers);
return <div>Headers Dynamic: {keys.join(", ")}</div>;
}
export default async function HeadersDynamic() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Headers />
</Suspense>
);
}
After saving, you should be able to see the headers without any errors.
Parameters
Next, let's examine parameterized routes. In Next.js 15, there's a significant change in how parameters are handled. Instead of receiving parameters as an object like in Next.js 14:
export default async function Params({ params }: { params: { id: string } }) {
const { id } = params;
return <div>Params: {id}</div>;
}
In Next.js 15, parameters are now received as a promise for performance reasons:
export default async function Params({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
return <div>Params: {id}</div>;
}
Keep in mind that you wouldn't want to cache these parameters.
Sometimes, dynamic imports may have issues with parameterized routes. If this happens, you can use Suspense
to fix it.
To do so, follow these steps:
- Create a new component for a non-default route.
- Create a new
ParamsDisplay
component and fetch the data using aPromise
. - Wrap the fetched data in a
Suspense
component.
import { Suspense } from "react";
async function ParamsDisplay({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return <div>Params: {id}</div>;
}
export default async function Params({
params,
}: {
params: Promise<{ id: string }>;
}) {
return (
<Suspense fallback={<div>Loading...</div>}>
<ParamsDisplay params={params} />
</Suspense>
);
}