reactjsnext.jsroutesdynamic

Hi i am using next.js (15.1.7) with react (19.0.0) for the file which is getting used for dynamic route when i create a build i get error


Here's my pacakge.json

{
  "name": "complex-routing-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "15.1.7",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "typescript": "^5"
  }
}

Here's the file which is taking id from the URL and then fetching it and displaying it

import styles from './page.module.css';
import { PostService } from '../service';
import Link from 'next/link';
import type { Metadata } from 'next';
import type { Post } from '@/app/types/post';

export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
    const awaitedParams = await params;
    const id = Number(awaitedParams.id);

    if (isNaN(id)) {
        return { title: 'Post Not Found' };
    }

    try {
        const post = await PostService.getPostById(id);
        return {
            title: post?.title || 'Post Not Found',
            description: post?.body?.substring(0, 150) || 'No description available.',
        };
    } catch {
        return { title: 'Post Not Found' };
    }
}

// ✅ Fetch post inside a separate function
async function fetchPostById(id: number): Promise<Post> {
    try {
        const response = await PostService.getPostById(id);
        if (!response) {
            throw new Error('Post not found');
        }
        return response;
    } catch (error) {
        throw new Error(error instanceof Error ? error.message : 'An error occurred while fetching the post.');
    }
}

// ✅ Correctly await params inside the component
export default async function Post({ params }: { params: { id: string } }) {
    const awaitedParams = await params;
    const id = Number(awaitedParams.id);

    if (isNaN(id)) {
        return (
            <div className={styles.errorContainer}>
                <div className={styles.ownaiLogo}>
                    <a href="https://ownai.net/" target="_blank" rel="noopener noreferrer">
                        own<b>AI</b>
                    </a>
                </div>
                <Link href="/posts" className={styles.backLink}>← Back to Posts</Link>
                <div className={styles.error}>Invalid Post ID.</div>
            </div>
        );
    }

    try {
        const post = await fetchPostById(id);

        return (
            <div className={styles.container}>
                <div className={styles.ownaiLogo}>
                    <a href="https://ownai.net/" target="_blank" rel="noopener noreferrer">
                        own<b>AI</b>
                    </a>
                </div>
                <div className={styles.header}>
                    <Link href="/posts" className={styles.backLink}>← Back to Posts</Link>
                    <h1 className={styles.title}>{post.title}</h1>
                    <div className={styles.metadata}>
                        <span className={styles.views}>👁 {post.views || 0} views</span>
                        <div className={styles.reactions}>
                            <span className={styles.likes}>👍 {post.reactions?.likes ?? 0}</span>
                            <span className={styles.dislikes}>👎 {post.reactions?.dislikes ?? 0}</span>
                        </div>
                    </div>
                    <div className={styles.tags}>
                        {post.tags?.map((tag: string) => (
                            <span key={tag} className={styles.tag}>{tag}</span>
                        ))}
                    </div>
                </div>
                <div className={styles.content}>
                    <p className={styles.postContent}>{post.body}</p>
                </div>
                <div className={styles.footer}>
                    <span className={styles.userId}>Post ID: {post.userId}</span>
                </div>
            </div>
        );
    } catch (error) {
        return (
            <div className={styles.errorContainer}>
                <div className={styles.ownaiLogo}>
                    <a href="https://ownai.net/" target="_blank" rel="noopener noreferrer">
                        own<b>AI</b>
                    </a>
                </div>
                <Link href="/posts" className={styles.backLink}>← Back to Posts</Link>
                <div className={styles.error}>{(error as Error).message}</div>
            </div>
        );
    }
}

now when i create a build using "npm run build" i get some type error as below


.next/types/app/posts/[id]/page.ts:34:29
Type error: Type '{ params: { id: string; }; }' does not satisfy the constraint 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ id: 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) {
Next.js build worker exited with code: 1 and signal: null

I am just starting with next.js so i am clueless why am i getting this error please help me to resolve this issue it would be really helpfull

Perviously i was using params id without async await but i was getting error "Error: Route "/posts/[id]" used params.id. params should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis" ans also in creating build i was getting error the same file.

So to resolve the issue of params should be awaited before using property that was the rason why did i add await before accessing the id object.

but now when i create the build i am getting some type related issue.


Solution

  • Instead of this

    export default async function Post({ params }: { params: { id: string } }) {
    

    use this

    export default async function Post({ params }: { params: Promise<{ id: string }> }) {
    

    I advise you to read migration guide: Upgrading from 14 to 15