Reputation: 185
I'm working on a Next.js 15 app using the new App Router (app directory) with dynamic route localization. I have a [locale] directory where I handle multiple language routes, and I use the params object to access the locale value. However, I keep getting the following error when trying to access params.locale:
Error: Route "/[locale]" used `params.locale`. `params` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
at locale (webpack:///app/[locale]/layout.tsx?a262:30:34)
Code Structure Here's the structure of my app:
app/
├── [locale]/
│ ├── layout.tsx // Root layout for [locale] dynamic route
│ └── page.tsx // Main page component for [locale] dynamic route
locales/
├── en/
│ └── common.json // English translations
├── lt/
│ └── common.json // Lithuanian translations
i18Config.js // i18n configuration with available locales
i18n.js // i18n initialization file
TranslationsProvider.js // Translation provider component
middleware.js // Middleware to handle locale-based redirection
In app/[locale]/layout.tsx, I want to access the locale value from params and pass it to different components. I have tried various ways to access params, but the error persists.
Here's what my layout.tsx file looks like:
import "@/styles/global.css";
import { Outfit } from "next/font/google";
import { Providers } from "./providers";
import i18nConfig from "../../i18nConfig";
import { dir } from "i18next";
const outfit = Outfit({
subsets: ["latin"],
weight: ["300", "400", "500", "600", "700", "800"],
style: ["normal"],
});
export function generateStaticParams() {
return i18nConfig.locales.map((locale) => ({ locale }));
}
export default async function RootLayout({
children,
params: { locale },
}: {
children: React.ReactNode;
params: { locale: string };
}) {
return (
<html
lang={locale}
dir={dir(locale)}
suppressHydrationWarning
className={outfit.className}
>
<body className="bg-background">
<Providers>{children}</Providers>
</body>
</html>
);
}
The error suggests that params should be "awaited," even though params is an object and not a promise, so await params doesn’t make sense here. I’ve seen other posts mentioning that destructuring in async functions can cause issues with params in Next.js, but accessing params directly also didn’t work for me. Restarting the server after every change didn’t resolve the issue either.
How can I correctly access params.locale in a dynamic route layout without getting this error? Is there a workaround or configuration I’m missing? Any insight would be greatly appreciated. Thank you!
Upvotes: 16
Views: 9178
Reputation: 1
In my case it was solved with this command
$ npx @next/codemod@canary next-async-request-api .
Upvotes: 0
Reputation: 767
I just found the problem (and it makes no sense at all).
This is the layout.tsx
code and it seems to be correct:
export default async function RootLayout({
children,
params,
}: RootLayoutProps) {
const { lang } = await params
return (
<html lang={lang}>
<body>{children}</body>
</html>
)
}
In my case, the icon.png
file was triggering the warning.
With warning:
/src
├── /app
│ ├── /[lang]
│ │ ├── layout.tsx
│ │ └── icon.png
Without warning:
/src
├── /app
│ ├── icon.png
│ ├── /[lang]
│ │ └── layout.tsx
That's it:
/app/[lang]/icon.png
- Warning/app/icon.png
- No warningUpvotes: 4
Reputation: 21
For reference, what you need to await is the params because, as Next15 Dynamic APIs are Asynchronous Official Docs
For example, you have a Page Component getting the id from the params like
export default async function Page(props: { params: { id: string } })
Then it would have to change to a Promise type like this:
export default async function Page(props: { params: Promise<{ id: string }> })
And access through the await of params like this:
const { id } = await props.params;
Upvotes: 1
Reputation: 13
export default async function RootLayout({
children,
params,
}: RootLayoutProps) {
const locale = (await params).locale
return (
<html lang={lang}>
<body>{children}</body>
</html>
)
}
Upvotes: 0
Reputation: 518
As of Next.js version 15 you must await the params to resolve this. Here is an example:
export default async function RootLayout({children, params }: { children: React.ReactNode; params: Promise<{ locale: string }> }) {
const { locale } = await params;
return()
}
let me know if it works for you.
Upvotes: 19
Reputation: 1396
You should await params, like:
export async function POST(request: Request, { params }: { params: Promise<{ unit_id: string }> }) {
and then:
const { unit_id: unitId } = await params
for example.
Upvotes: 1