javascriptreactjstypescriptnext.js

Route "/[locale]" used `params.locale`. `params` should be awaited before using its properties


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>
  );
}

  1. Accessing params directly in the function body: I've moved params.locale to a separate constant in the function body, but the error still appears.
  2. Using generateStaticParams: I added generateStaticParams to pre-generate routes for the available locales (en and lt). This didn't resolve the error either.
  3. Type Adjustments: I created a custom type for params to ensure TypeScript knows the structure of params (i.e., params: { locale: string }).

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!


Solution

  • 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: