13

I recently upgraded to Next.js 15, and I'm facing an issue when trying to access params in a dynamic route.

Folder structure:

/app  
  /product  
    /[id]  
      /page.tsx  

When I try to access the id from params in my [id]/page.tsx, I get this error:

A param property was accessed directly with params.id. params is now a Promise and should be unwrapped with React.use() before accessing properties of the underlying params object. In this version of Next.js direct access to param properties is still supported to facilitate migration, but in a future version, you will be required to unwrap params with React.use().

app/product/[id]/page.tsx):

export default async function Page({ params }: { params: { id: string } }) {
  const id = params.id; // This throws the error
  return <div>Product ID: {id}</div>;
}

I tried changing the function signature to this:

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params; 
  return <div>Product ID: {id}</div>;
}

This works, but I'm unsure if it's the correct approach.

I reviewed the Next.js 15 documentation, but there's no clear mention of this behavior change.

Questions:

  1. Is this the correct way to handle params in Next.js 15?
  2. Why is params now a Promise, and is this an intentional breaking change for future versions?
2
  • Yes your approach using the promise is correct. From NextJS 15, the params and searchParams are now asynchronous. You can check my answer to the same question here: stackoverflow.com/questions/79455298/… Commented Feb 25 at 13:00
  • Yes, this is correct way Commented Feb 25 at 14:37

2 Answers 2

21

The solution sent by Jasperan may solve the problem, but I hate having to create a "use server" component just to load another "use client" component, when you could just have a single component. I really hate this kind of approach.

The solution for this is actually quite simple: https://github.com/vercel/next.js/issues/71690#issuecomment-2439644682

You can use the react API called "use": https://react.dev/reference/react/use

'use client';

import { use } from 'react';

export default function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = use(params); 
  return <div>Product ID: {id}</div>;
}
Sign up to request clarification or add additional context in comments.

2 Comments

When using your solution, there is typescript warning Argument of type '{ params: Promise<{ id: string; }>; }' is not assignable to parameter of type 'Usable<unknown>'.ts(2345)
I get the same error, it looks like this solution provided by Next.js did not take Typescript into account :/
5

You're correct that you need to use await in Next.js 15 to extract params now (see Next.js docs for an example). This needs to be done in a server component since client components cannot be async.

If you need the params in your client component, you can extract it in a server component first and then pass it down, like so:

/product/[id]/page.tsx (server component)

import ProductPage from "./productPage";

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;

  return <ProductPage id={id} />;
}

Then in your client component:

/product/[id]/productPage.tsx (client component)

"use client";

export default function ProductPage({ id }: { id: string }) {
  return <div>{id}</div>;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.