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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:25:20