You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13.4:如何同时实现URL参数获取与静态预渲染?

问题:Next.js 13.4 动态路由静态预渲染与URL参数获取共存方案

问题背景

在Next.js 13.4中创建了/notes/[note]动态路由页面,需要同时实现两个需求:

  • 获取URL中的note参数
  • 通过generateStaticParams预渲染指定的4个note ID对应的静态HTML文件

但遇到矛盾问题:

  • 服务器组件模式下,使用useParams会报错,无法正常获取参数
  • 添加'use client'声明转为客户端组件后,静态预渲染失效,构建时不会生成指定的4个HTML文件

附原代码:

'use client'
import styles from '../../page.module.css'
import { useParams } from 'next/navigation'

async function getNoteData(id : string) {
  const note = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
  if(!note) {
    throw new Error("No data found.");
  }
  return note.json();
}

interface Note {
  userId: string;
  id: number;
  title: string;
  completed: string;
}

export function generateStaticParams() {
  return [{note: '1'}, {note: '2'}, {note: '3'}, {note: '4'}]
}

export default async function Note({params}: {params: {note: string}}) {
  const param = useParams();
  const todo : Note = await getNoteData(param.note);
  return (
    <main className={styles.main}>
      <h1>Note Page</h1>
      <div className={styles.description}>
          <p>{todo?.title}</p>
      </div>
    </main>
  )
}

解决方案

核心逻辑

  • useParams是客户端专属钩子,仅能在客户端组件中使用,但客户端组件无法触发generateStaticParams完成静态预渲染
  • 服务器组件可直接通过组件props接收params参数,同时完美支持generateStaticParams生成静态页面,无需额外客户端钩子

修正后的代码

import styles from '../../page.module.css'

async function getNoteData(id: string) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
    cache: 'force-cache' // 显式指定缓存策略,确保静态预渲染时缓存数据
  });
  if (!res.ok) {
    throw new Error("No data found.");
  }
  return res.json();
}

interface Note {
  userId: number; // 修正类型:接口返回的userId为数字类型
  id: number;
  title: string;
  completed: boolean; // 修正类型:completed为布尔值类型
}

export function generateStaticParams() {
  return [{ note: '1' }, { note: '2' }, { note: '3' }, { note: '4' }]
}

export default async function Note({ params }: { params: { note: string } }) {
  // 直接通过props获取params,无需useParams
  const todo: Note = await getNoteData(params.note);
  return (
    <main className={styles.main}>
      <h1>Note Page</h1>
      <div className={styles.description}>
        <p>标题:{todo.title}</p>
        <p>完成状态:{todo.completed ? '已完成' : '未完成'}</p>
      </div>
    </main>
  )
}

关键修改点

  1. 移除'use client'声明和useParams导入,保持组件为服务器组件
  2. 直接通过组件props的params.note获取URL动态参数
  3. 修正Note接口的类型错误,匹配接口实际返回的数据类型
  4. 给fetch添加cache: 'force-cache'(默认值,显式声明更清晰),确保静态预渲染时缓存请求结果

验证效果

运行npm run build后,.next/server/app/notes目录下会生成1.html、2.html、3.html、4.html四个静态文件,同时页面能正常获取并展示对应note的数据。

内容的提问来源于stack exchange,提问作者Umair Jameel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:12:59