Next.js从Pages Router迁移到App Router:动态数据获取问题
Next.js Pages Router 到 App Router 迁移(动态数据场景)
针对你迁移时遇到的动态数据获取问题,下面是对应代码的完整迁移方案,完全对齐原逻辑:
迁移后完整代码(app/pet/[id]/page.js)
'use client'; // 标记为客户端组件,因为用到了useState和客户端路由操作 import { useState } from 'react'; import Link from 'next/link'; import { useRouter, useParams } from 'next/navigation'; import dbConnect from '@/lib/dbConnect'; // 路径别名可根据项目配置调整 import Pet from '@/models/Pet'; /* 查看宠物卡片信息并支持删除操作 */ export default async function PetPage() { const params = useParams(); const router = useRouter(); const [message, setMessage] = useState(''); // 服务器端获取宠物数据(App Router支持异步页面组件,自动在服务端执行) await dbConnect(); const pet = await Pet.findById(params.id).lean(); pet._id = pet._id.toString(); const handleDelete = async () => { const petID = params.id; // 直接从useParams获取动态路由ID,替代原router.query.id try { await fetch(`/api/pets/${petID}`, { method: 'DELETE', }); router.push('/'); } catch (error) { setMessage('删除宠物失败'); } }; return ( <div key={pet._id}> <div className="card" style={{ width: '1000px' }}> <img src={pet.image_url} alt={pet.name} /> <h5 className="pet-name">{pet.name}</h5> <div className="main-content"> <p className="pet-name">{pet.name}</p> <p className="owner">主人: {pet.owner_name}</p> {/* 宠物喜好信息 */} <div className="likes info"> <p className="label">喜欢的事物</p> <ul> {pet.likes.map((data, index) => ( <li key={index}>{data}</li> ))} </ul> </div> <div className="dislikes info"> <p className="label">讨厌的事物</p> <ul> {pet.dislikes.map((data, index) => ( <li key={index}>{data}</li> ))} </ul> </div> <div className="btn-container"> {/* App Router中Link的新用法,直接传入完整路径 */} <Link href={`/pet/${pet._id}/edit`}> <button className="btn edit">编辑</button> </Link> <button className="btn delete" onClick={handleDelete}> 删除 </button> </div> </div> </div> {message && <p>{message}</p>} </div> ); }
关键迁移点说明
- 页面结构调整:App Router中动态路由页面必须放在
app/pet/[id]/page.js路径下,对应原Pages Router的pages/pet/[id].js,确保和你的动态链接/pet/${item._id}匹配 - 数据获取逻辑迁移:原
getServerSideProps的代码直接移到页面组件内部,App Router支持异步页面组件,这段异步代码会自动在服务器端执行 - 动态参数获取替换:
- 客户端操作(比如删除按钮)用
useParams()获取动态路由的id,替代原useRouter().query.id - 因为用到了
useState和客户端路由方法,必须在组件顶部加上'use client'指令,标记为客户端组件
- 客户端操作(比如删除按钮)用
- 路由操作更新:
- 原
useRouter从next/router改为从next/navigation导入 - Link组件不再需要
legacyBehavior和as属性,直接传入完整的目标路径即可
- 原
- 路径优化:建议用
@/替代相对路径,需要在next.config.js中配置路径别名(如果之前没配置)
额外注意
- 若编辑页面
/pet/${id}/edit也需要迁移,需放在app/pet/[id]/edit/page.js路径下 - 原API路由
pages/api/pets/[id].js无需改动,可继续使用
内容的提问来源于stack exchange,提问作者Febry Aryo
相关产品推荐
相关产品推荐

