
在 Next.js App Router 中,useRouter().query 不可用,应改用 useParams() 获取动态路由参数,否则会因 router.query 为 undefined 导致解构错误。
在 next.js app router 中,动态路由参数获取方式已发生根本性变化:`userouter().query` 不再适用,直接解构 `router.query.id` 会导致 `typeerror: cannot destructure property 'id' of 'router.query' as it is undefined`。必须使用 `useparams()` hook 从 url 路径中安全提取参数。
Next.js 13+ 的 App Router(即 app/ 目录结构)已弃用传统的 router.query 模式。你当前的文件路径 app/shop/[id]/page.tsx 明确属于 App Router,因此:
✅ 正确做法:使用 useParams() 获取动态段参数
❌ 错误做法:调用 useRouter().query(该对象在 App Router 中始终为 undefined)或尝试 import { useRouter } from 'next/route'(该路径不存在,属拼写错误)
以下是修复后的完整示例代码:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
"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] 动态参数 —— 返回 string | string[]
useEffect(() => {
const fetchData = async () => {
// 注意:useParams() 返回的 id 可能是字符串数组(如嵌套路由),此处单级动态路由下为 string
if (typeof id === '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>Loading shop data...</div>;
return (
<div>
<h1>Shop ID: {id}</h1>
<pre class="brush:php;toolbar:false;">{JSON.stringify(shopData, null, 2)}
);
}⚠️ 关键注意事项:
-
useParams()是 Server Component 兼容的 Client Component Hook,仅在'use client'组件中可用; -
useParams()返回值类型为Record<string string></string>,对单层动态路由(如[id]),id通常为string,但仍建议运行时校验(如typeof id === 'string'); - 不要混用旧版 Page Router 的
next/router—— App Router 下import { useRouter } from 'next/router'会返回空query对象,且useRouter在服务端渲染阶段不可用; - 若需监听路由变化(如前进/后退),可配合
usePathname()或useSearchParams()使用,但参数获取请始终以useParams()为准。
总结:App Router 的设计哲学是“路径即参数”,useParams() 是官方推荐、类型安全、SSR 友好的唯一标准方式。摒弃 router.query 思维,是避免此类运行时错误的根本解法。


















