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> ) }
关键修改点
- 移除
'use client'声明和useParams导入,保持组件为服务器组件 - 直接通过组件props的
params.note获取URL动态参数 - 修正
Note接口的类型错误,匹配接口实际返回的数据类型 - 给
fetch添加cache: 'force-cache'(默认值,显式声明更清晰),确保静态预渲染时缓存请求结果
验证效果
运行npm run build后,.next/server/app/notes目录下会生成1.html、2.html、3.html、4.html四个静态文件,同时页面能正常获取并展示对应note的数据。
内容的提问来源于stack exchange,提问作者Umair Jameel
相关产品推荐
相关产品推荐

