关于 nextjs-pathname-id-fetch
面向 Next.js 开发者的路径标识符取数技能,聚焦于通过动态路由参数获取页面数据。它强调使用服务端组件、在 Next.js 15+ 等待 params,并保持路由结构简洁。
主要功能
- 01创建带括号的动态路由段
- 02从 params 读取标识符
- 03依据路径参数获取数据
- 04使用服务端组件处理页面
- 05为参数定义明确类型
适用场景
- 01按产品 ID 加载详情页
- 02按文章 slug 获取内容
- 03按管理路径中的订单 ID 查询数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ wsimmonds/ claude-nextjs-skills --skill nextjs-pathname-id-fetch安装后在 Claude Code 中输入/nextjs-pathname-id-fetch确认已加载。
详细介绍
Next.js:按路径名 ID 获取数据模式
适用场景
只要页面需要根据 URL 中的标识符加载数据,就可以使用此模式。常见场景包括:
- 产品、文章或用户详情页(
/products/{id}、/blog/{slug}) - 可逐层查看所选资源的管理控制面板(
/admin/orders/{orderId}) - 具有嵌套路径的文档或知识库(
/docs/getting-started/installation)
如果需求要求数据随当前 URL 路径变化,路由段必须是动态的(例如 [id]、[slug]、[...slug])。
模式
✅ 推荐实现
1. Create a dynamic folder: app/[id]/page.tsx
2. Access the parameter: const { id } = await params;
3. Fetch data using that identifier
4. Render the requested information
❌ 易错点
Using app/page.tsx for this scenario prevents access to per-path identifiers.
完整实现示例
// app/[id]/page.tsx
// IMPORTANT: Server component (NO 'use client' needed!)
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
// Next.js 15+: params must be awaited
const { id } = await params;
// Fetch data using the ID from the URL
const response = await fetch(`https://api.example.com/products/${id}`);
const product = await response.json();
// Return JSX with the fetched data
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>Price: ${product.price}</p>
</div>
);
}
文件结构
app/
└── [id]/ ← Dynamic route folder with brackets
└── page.tsx ← Server component page
URL 映射:
/123→ params ={ id: '123' }/abc→ params ={ id: 'abc' }/product-xyz→ params ={ id: 'product-xyz' }
关键规则
1. 文件夹名称必须使用方括号
✅ app/[id]/page.tsx
✅ app/[productId]/page.tsx
✅ app/[slug]/page.tsx
❌ app/id/page.tsx (no brackets = static route)
❌ app/page.tsx (can't access params here)
2. 这是一个服务端组件(默认)
// ✅ CORRECT - No 'use client' needed
export default async function Page({ params }) {
const { id } = await params;
const data = await fetch(`/api/${id}`);
return <div>{data.name}</div>;
}
// ❌ WRONG - Don't add 'use client' for server components
'use client'; // ← Remove this!
export default async function Page({ params }) { ... }
3. 必须等待 params(Next.js 15+)
// ✅ CORRECT - Next.js 15+
export default async function Page({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params; // Must await
// ...
}
// ⚠️ OLD (Next.js 14 and earlier - deprecated)
export default async function Page({
params,
}: {
params: { id: string };
}) {
const { id } = params; // No await needed in old versions
// ...
}
4. 保持简单——不要过度嵌套
✅ app/[id]/page.tsx (simple, clean)
❌ app/products/[id]/page.tsx (only if explicitly required!)
除非需求明确要求使用 /products/[id],否则将结构保持在顶层(app/[id]/page.tsx)。
TypeScript:切勿使用 any 类型
此代码库启用了 @typescript-eslint/no-explicit-any。使用 any 会导致构建失败。
// ❌ WRONG
function processProduct(product: any) { ... }
// ✅ CORRECT - Define proper types
interface Product {
id: string;
name: string;
price: number;
}
function processProduct(product: Product) { ... }
// ✅ ALSO CORRECT - Use unknown if type truly unknown
function processData(data: unknown) {
// Type guard required before using
if (typeof data === 'object' && data !== null) {
// ...
}
}
常见变体
不同的参数名称
// app/[productId]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ productId: string }>;
}) {
const { productId } = await params;
// ...
}
// app/[slug]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
// ...
}
多个参数
// app/[category]/[id]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ category: string; id: string }>;
}) {
const { category, id } = await params;
const data = await fetch(`/api/${category}/${id}`);
// ...
}
完整可运行示例
// app/[id]/page.tsx - Product detail page
interface Product {
id: string;
name: string;
description: string;
price: number;
inStock: boolean;
}
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
// Get the ID from the URL
const { id } = await params;
// Fetch product data using the ID
const response = await fetch(
`https://api.example.com/products/${id}`,
{ cache: 'no-store' } // Always fresh data
);
if (!response.ok) {
throw new Error('Failed to fetch product');
}
const product: Product = await response.json();
// Render the product
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<div>
<strong>Price:</strong> ${product.price}
</div>
<div>
<strong>Availability:</strong>{' '}
{product.inStock ? 'In Stock' : 'Out of Stock'}
</div>
</div>
);
}
快速检查清单
发布由路径名驱动的详情页前,请确认:
- 路由文件夹使用方括号(例如
app/[id]/page.tsx) - 组件保持在服务端运行(无需使用
'use client') - 对于 Next.js 15+,
params属性的类型为Promise<{ id: string }> - 等待 params 并安全地读取标识符
- 数据获取逻辑使用该标识符
- 渲染逻辑适当地处理加载和错误状态
- 类型明确——绝不退而使用
any
何时改用完整技能
此微技能介绍了简单的“按路径名 ID 获取数据”模式。以下情况请使用完整的 nextjs-dynamic-routes-params 技能:
- 捕获所有路由(
[...slug]) - 可选捕获所有路由(
[[...slug]]) - 复杂的多参数路由
- 高级路由架构
- 详细的路由决策
对于“按 URL 中的 ID 获取数据”这一简单场景,此技能已足够。
评论
支持 Markdown