Next.js Discord

Discord Forum

I can't build in Next Js 15.0.2 due to params in a page (dynamic segment)

Answered
West African Crocodile posted this in #help-forum
Open in Discord
West African CrocodileOP
Hi there,

I searched other threads before creating. Found similar questions. But the approved solutions are not working for me. So I'm creating mine.

This code works while I do pnpm run dev, I can see the post loaded.

// app/blog/[slug]/page.tsx
import { notFound } from "next/navigation";
import BlogPost from "@/components/BlogPost";
import db from "@/db/index";
import { Post } from "@/db/schema";
import { eq } from "drizzle-orm";

type Props = {
  params: Promise<{ slug: string }>;
};

export default async function Page(props: Props) {
  const { slug } = await props.params;

  const post = await db.select().from(Post).where(eq(Post.slug, slug)).limit(1);

  if (!post.length) {
    notFound();
  }

  return <BlogPost post={post[0]} />;
}


But If I do pnpm run build then I get this error:

   Linting and checking validity of types  .Failed to compile.

.next/types/app/blog/page/[page]/page.ts:34:29
Type error: Type '{ params: { page: string; }; }' does not satisfy the constraint 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ page: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]

  32 |
  33 | // Check the prop type of the entry function
> 34 | checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>()
     |                             ^
  35 |
  36 | // Check the arguments and return type of the generateMetadata function
  37 | if ('generateMetadata' in entry) {
 ELIFECYCLE  Command failed with exit code 1.


I also tried with things like params: Promise<{slug: string}> | {slug:string}

And matched how it was done here:
https://nextjs.org/docs/canary/app/building-your-application/upgrading/version-15#asynchronous-page
https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes
https://nextjs-forum.com/post/1299939488654561361

I'm being unable to solve the problem.
What I'm doing wrong ?
Answered by joulev
params: Promise<{ page: string }> instead of { page: string }
View full answer

39 Replies

That is a error in types I believe
Can you send type of BlogPost?
West African CrocodileOP
Hi @"use php" !
I'm using drizzle orm (or trying 😅 )

So the types for the BlogPost are the inferred types from the Schema.

import { SelectPost } from "@/db/schema";

interface BlogPostProps {
  post: SelectPost;
}

export default function BlogPost({ post }: BlogPostProps) {


I'm "glob importing" it from src\db\schema\index.ts with export * from "./post";

And this is the schema:

import { InferSelectModel, InferInsertModel, sql } from "drizzle-orm";
import { pgTable as table } from "drizzle-orm/pg-core";
import * as t from "drizzle-orm/pg-core";

const timestamps = {
  updatedAt: t.timestamp({ withTimezone: true, mode: "string" }),
  createdAt: t
    .timestamp({ withTimezone: true, mode: "string" })
    .defaultNow()
    .notNull(),
  deletedAt: t.timestamp({ withTimezone: true, mode: "string" }),
};

export const Post = table(
  "Post",
  {
    id: t.integer().primaryKey().generatedAlwaysAsIdentity(),
    title: t.text().notNull(),
    slug: t.text().notNull().unique(),
    excerpt: t.text().notNull(),
    author: t.text().notNull(),
    category: t.text().notNull(),
    tags: t
      .text()
      .array()
      .notNull()
      .default(sql`ARRAY[]::text[]`),
    readingTime: t.integer().notNull(),
    content: t.text().notNull(),
    components: t
      .text()
      .array()
      .notNull()
      .default(sql`ARRAY[]::text[]`),
    ...timestamps,
  },
  (table) => {
    return {
      slugIndex: t.uniqueIndex("slug_idx").on(table.slug),
      titleIndex: t.index("title_idx").on(table.title),
    };
  }
);

export type SelectPost = InferSelectModel<typeof Post>;
export type InsertPost = InferInsertModel<typeof Post>;


I thought my schema types should have something to do with the error... but v0.dev told me it was a problem with it being awaited and so... So I got pretty confused with these new async changes I think.
if build is running on prod, have you added env variables?
West African CrocodileOP
I've used this to connect.
My .env just have DATABASE_URL=....the connection string....
I was just trying to build on localhost
import "dotenv/config";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";

import * as schema from "@/db/schema";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL!,
});

const db = drizzle(pool, {
  schema,
  logger: true,
});

// export type db = typeof db;

export default db;
are you running build locally?
West African CrocodileOP
pnpm run build

yep 😀
I'm unsure about drizzle can you try using as when setting types, and see if you still get the error
and also console log the item
West African CrocodileOP
Uhmm... I only saw the usage of as here:
https://nextjs.org/docs/canary/app/building-your-application/upgrading/version-15#asynchronous-page

Like: const cookieStore = cookies() as unknown as UnsafeUnwrappedCookies

There's also something similar for draftMode and headers but not for page, at least there.

Is this what you mean ? There should be an UnsafeUnwrappedPage too ? I'm not really sure what should use for as in my case.
Oh... I'm seeing next/server has this:
export type { UnsafeUnwrappedParams } from 'next/dist/server/request/params'
No, in db operation
When you read from db
West African CrocodileOP
This ?
const post = await db.select().from(Post).where(eq(Post.slug, slug)).limit(1);
Yup, try to set as type. Also console log the post
West African CrocodileOP
I tried to use as Post and as SelectPost but doesn't seem to like it 😅
Light theme sorry 😅
In theory, with drizzle, I'm already passing the type, in the .from(Post) It's all what it needs to make the select.
In fact, I can load the page with the data when running with pnpm run dev
mid english, mid spanish 😅
@West African Crocodile Hi there, I searched other threads before creating. Found similar questions. But the approved solutions are not working for me. So I'm creating mine. This code works while I do `pnpm run dev`, I can see the post loaded. typescript // app/blog/[slug]/page.tsx import { notFound } from "next/navigation"; import BlogPost from "@/components/BlogPost"; import db from "@/db/index"; import { Post } from "@/db/schema"; import { eq } from "drizzle-orm"; type Props = { params: Promise<{ slug: string }>; }; export default async function Page(props: Props) { const { slug } = await props.params; const post = await db.select().from(Post).where(eq(Post.slug, slug)).limit(1); if (!post.length) { notFound(); } return <BlogPost post={post[0]} />; } But If I do `pnpm run build` then I get this error: Linting and checking validity of types .Failed to compile. .next/types/app/blog/page/[page]/page.ts:34:29 Type error: Type '{ params: { page: string; }; }' does not satisfy the constraint 'PageProps'. Types of property 'params' are incompatible. Type '{ page: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag] 32 | 33 | // Check the prop type of the entry function > 34 | checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>() | ^ 35 | 36 | // Check the arguments and return type of the generateMetadata function 37 | if ('generateMetadata' in entry) {  ELIFECYCLE  Command failed with exit code 1. I also tried with things like `params: Promise<{slug: string}> | {slug:string}` And matched how it was done here: <https://nextjs.org/docs/canary/app/building-your-application/upgrading/version-15#asynchronous-page> <https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes> <https://discord.com/channels/752553802359505017/1299939488654561361> I'm being unable to solve the problem. What I'm doing wrong ?
The bug is in app/blog/page/[page]/page.tsx, not app/blog/[slug]/page.tsx
West African CrocodileOP
oh maybe not the type, just the schema.... but meh it work on dev.
The bug is not relevant to drizzle or blog content or anything
Paste the prop type of app/blog/page/[page]/pags.tsx here
West African CrocodileOP
ohhhh
the route is other : /
It's true I have some different routes, where I'm trying different things.
Ah yes, this is where I tried to implement a pagination.

import { PaginationComponent } from "@/components/Pagination";
import { getBlogPosts } from "@/lib/blog";

export default async function BlogPage({
  params,
}: {
  params: { page: string };
}) {
  const { page } = await params;
  const currentPage = parseInt(page, 10) || 1;
  const { posts, totalPages } = await getBlogPosts(currentPage, 2);

  return (
    <div>
      {/* Render your blog posts here */}
      <ul className="flex flex-col gap-4">
        {posts.map((post, index) => (
          <li key={index}>
            <h2>{post.title}</h2>
            <p>{post.excerpt}</p>
            <p>Published on: {new Date(post.createdAt).toLocaleDateString()}</p>
            {post.updatedAt && (
              <p>Updated on: {new Date(post.updatedAt).toLocaleDateString()}</p>
            )}
            <p>Category: {post.category}</p>
            <p>Author: {post.author}</p>
            <p>Reading time: {post.readingTime}</p>
            <p>Tags: {post.tags.join(", ")}</p>
          </li>
        ))}
      </ul>

      <PaginationComponent
        currentPage={currentPage}
        totalPages={totalPages}
        maxPageNumbers={3}
      />
    </div>
  );
}
Answer
West African CrocodileOP
I'm trying to build after changing it
haha my app feels like a mine field atm....
   Linting and checking validity of types  ..Failed to compile.

.next/types/app/post/page.ts:2:24
Type error: File 'C:/dev/nextjs/next-stable-pnpm/src/app/post/page.tsx' is not a module.

  1 | // File: C:\dev\nextjs\next-stable-pnpm\src\app\post\page.tsx
> 2 | import * as entry from '../../../../src/app/post/page.js'
    |                        ^
  3 | import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
  4 |
  5 | type TEntry = typeof import('../../../../src/app/post/page.js')
 ELIFECYCLECommand failed with exit code 1.
another file....
so my initial problem is solved I guess
I need 5 min, then I could check further (bit busy)
West African CrocodileOP
Sure, many thanks for helping me 🙂 both of you !