
在 Next.js App Router 中,useRouter().query 已被弃用,直接解构 router.query.id 会报错;应改用 useParams() 获取动态路由参数,而非 usePathname 或旧版 next/router。
在 next.js app router 中,`userouter().query` 已被弃用,直接解构 `router.query.id` 会报错;应改用 `useparams()` 获取动态路由参数,而非 `usepathname` 或旧版 `next/router`。
Next.js 自 13.4 起全面推荐使用 App Router(基于 app/ 目录),其路由参数处理机制与旧版 Page Router 截然不同。你当前的路径 app/shop/[id]/page.tsx 明确属于 App Router 体系,因此绝不能使用 next/router(Page Router 专属),也不应依赖 router.query——它在 App Router 中始终为 undefined,导致 TypeError: Cannot destructure property 'id' of 'router.query' as it is undefined。
✅ 正确做法:使用 useParams() 钩子useParams() 是 App Router 官方提供的、专用于读取动态段(如 [id])值的 React Hook,返回一个包含所有命名动态参数的对象:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
"use client";
import { useState, useEffect } from 'react';
import { useParams } from 'next/navigation'; // ✅ 正确导入
export default function ShopPage() {
const [shopData, setShopData] = useState<any>(null);
const { id } = useParams(); // ✅ 直接解构 id,类型安全(id 为 string | string[])
useEffect(() => {
const fetchData = async () => {
if (!id) return; // 安全防护:id 可能为数组(如 /[id]/[slug]),但单层动态路由下通常为 string
try {
const response = await fetch(`/api/shop/${id}`);
if (response.ok) {
const result = await response.json();
setShopData(result.shop);
} else {
console.error('Failed to fetch shop:', response.statusText);
}
} catch (error) {
console.error('Error fetching shop:', error);
}
};
fetchData();
}, [id]); // ✅ 依赖项包含 id,确保路由变化时重新请求
if (!id) return <div>Loading...</div>;
if (!shopData) return <div>Fetching shop details...</div>;
return (
<div>
<h1>Shop ID: {id}</h1>
<pre class="brush:php;toolbar:false;">{JSON.stringify(shopData, null, 2)}
);
}⚠️ 关键注意事项:
-
useParams()仅在客户端组件中可用(故需"use client"),且必须在组件顶层调用; -
id类型默认为string | string[],若确定是单值动态段(如/shop/[id]),可添加类型断言:const { id } = useParams();; - ❌ 不要使用
usePathname()替代:它返回完整路径字符串(如/shop/123),需手动解析,既不健壮也不符合设计意图; - ❌ 禁止混用
next/router:该模块仅适用于pages/目录下的 Page Router,与app/目录不兼容,强行引入将触发useRouter is not mounted错误; - 若需服务端预渲染数据,建议直接在
page.tsx中使用async组件 +fetch(无需useEffect),提升性能与 SEO。
总结:App Router 的动态参数获取是声明式、静态可分析的,useParams() 是唯一官方推荐方式。摒弃 router.query 思维,拥抱 useParams(),即可彻底解决参数 undefined 报错问题,并写出更可靠、可维护的 Next.js 应用。


















