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

Next.js 13实验性App目录动态路由生成问题求助

Next.js 13 App Router 狗狗救助站动态路由问题解决方案

问题背景

开发非营利性狗狗救助站网站,使用Next.js 13实验性App目录搭配@apollo/client和GraphQL实现狗狗列表动态路由。点击列表链接进入详情页时,dog变量显示为undefined,仅动态路由页面出现错误,旧版Next.js可正常实现但不想回退版本。

错误原因分析

  1. API不兼容:App Router不支持Pages Router的getStaticProps和getStaticPaths API,这两个方法在App Router中已被废弃。
  2. 导入路径错误:动态路由页面中错误导入了@/libs/graphql(应为@/libs/client)和@/graphql/perritos(应为@/graphql/dogs),导致数据获取失败。
  3. 客户端组件限制:错误给页面添加"use client"指令,若无需客户端交互,服务器组件更适合数据获取场景,且客户端组件无法直接通过旧API接收服务器端生成的props。

修复步骤及代码示例

1. 修正导入路径

确保动态路由页面的导入路径与实际文件结构一致:

  • 替换import { client } from "@/libs/graphql";为import { client } from "@/libs/client";
  • 替换import { GET_DOGGIES, GET_DOG } from "@/graphql/perritos";为import { GET_DOGGIES, GET_DOG } from "@/graphql/dogs";

2. 替换静态生成API

使用App Router的generateStaticParams替代getStaticPaths,并在服务器组件内部异步获取数据(替代getStaticProps)。

修改后的./app/dogs/[slug]/page.jsx代码:

import { client } from "@/libs/client";
import { GET_DOGGIES, GET_DOG } from "@/graphql/dogs";

// 生成静态路由路径,替代原getStaticPaths
export async function generateStaticParams() {
  const { data } = await client.query({
    query: GET_DOGGIES,
  });

  return data.dogs.data.map((d) => ({
    slug: d.attributes.slug,
  }));
}

// 服务器组件异步获取数据并渲染
export default async function Doggie({ params }) {
  const { data } = await client.query({
    query: GET_DOG,
    variables: { slug: params.slug },
  });

  const dog = data.dog.data;

  // 空值判断避免报错
  if (!dog) {
    return <div>狗狗不存在</div>;
  }

  return (
    <div>
      <h1>{dog.attributes.name}</h1>
      <p>{dog.attributes.desc}</p>
    </div>
  );
}

3. (可选)支持客户端交互

若页面需要客户端交互逻辑(如点击事件、状态管理),可拆分服务器组件与客户端组件:

服务器组件./app/dogs/[slug]/page.jsx

import { client } from "@/libs/client";
import { GET_DOGGIES, GET_DOG } from "@/graphql/dogs";
import DoggieClient from "./DoggieClient";

export async function generateStaticParams() {
  const { data } = await client.query({
    query: GET_DOGGIES,
  });

  return data.dogs.data.map((d) => ({
    slug: d.attributes.slug,
  }));
}

export default async function Doggie({ params }) {
  const { data } = await client.query({
    query: GET_DOG,
    variables: { slug: params.slug },
  });

  const dog = data.dog.data;

  if (!dog) {
    return <div>狗狗不存在</div>;
  }

  // 将数据传递给客户端组件
  return <DoggieClient dog={dog} />;
}

客户端组件./app/dogs/[slug]/DoggieClient.jsx

"use client";

export default function DoggieClient({ dog }) {
  // 在此添加客户端交互逻辑,如按钮点击、状态管理等
  return (
    <div>
      <h1>{dog.attributes.name}</h1>
      <p>{dog.attributes.desc}</p>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Afx Crush

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:08:21