Next.js中router.query.id解构报错问题排查求助
问题
错误信息
Cannot destructure property 'id' of 'router.query' as it is undefined
相关代码
// data.js export const data = { orders: [ { id: 1, customer: "Customer A", items: [ { id: 1, name: "Item 1", quantity: 5 }, { id: 2, name: "Item 2", quantity: 3 } ], status: "Pending" }, { id: 2, customer: "Customer B", items: [ { id: 1, name: "Item 1", quantity: 2 }, { id: 3, name: "Item 3", quantity: 1 } ], status: "Completed" } ], items: [ { id: 1, name: "Item 1", stock: 20 }, { id: 2, name: "Item 2", stock: 15 }, { id: 3, name: "Item 3", stock: 10 } ] };
// [id]/page.js "use client"; import { useRouter } from "next/navigation"; import { data } from "../../../utils/data"; const OrderDetails = () => { const router = useRouter(); const { id } = router.query; if (!id) { return <div>No order ID provided</div>; } const order = data.orders.find(order => order.id === parseInt(id)); if (!order) { return <div>Order not found</div>; } return ( <div className="container mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">Order Details - {order.id}</h1> <p>Customer: {order.customer}</p> <p>Status: {order.status}</p> <h2 className="text-xl font-semibold ">Items: </h2> <ul> { order.items.map(item => ( <li key={item.id} className="border-b py-2"> <p>Name: {item.name}</p> <p>Quantity: {item.quantity}</p> <p>Stock: {data.items.find(i => i.id === item.id).stock}</p> </li> )) } </ul> <button className="mt-4 bg-green-500 text-white px-4 py-2 rounded">Mark as Completed</button> </div> ); }; export default OrderDetails;
// orders/page.js "use client"; import { useEffect, useState } from "react"; import { data } from "../../utils/data"; import Link from 'next/link'; const OrderList = () => { const [orders, setOrders] = useState(data.orders); const [filter, setFilter] = useState(''); useEffect(() => { if (filter) { setOrders(data.orders.filter(order => order.status === filter)); } else { setOrders(data.orders); } }, [filter]); return ( <div className="container mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">Orders List</h1> <div className="mb-4"> <label htmlFor="statusFilter" className="mr-2">Filter by status:</label> <select id="statusFilter" onChange={e => setFilter(e.target.value)} className="border rounded px-2 py-1 bg-black" > <option value="">All</option> <option value="Pending">Pending</option> <option value="Completed">Completed</option> </select> </div> <ul> {orders.map(order => ( <li key={order.id} className="border-b py-2"> <div className="flex justify-between"> <div> <h2 className="text-xl font-semibold">Order ID: {order.id}</h2> <p>Customer: {order.customer}</p> <p>Status: {order.status}</p> <p>Item Count: {order.items.length}</p> </div> <Link href={`/orders/` + orders.id}> <button className="text-blue-500">View Details</button> </Link> </div> </li> ))} </ul> </div> ); }; export default OrderList;
// inventory/page.js "use client"; import { useState } from "react"; import { data } from "../../utils/data"; const InventoryList = () => { const [items, setItems] = useState(data.items); const handleDelete = (id) => { setItems(items.filter(item => item.id !== id)); }; return ( <div className="container mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">Inventory List</h1> <ul> {items.map(item => ( <li key={item.id} className="border-b py-2 flex justify-between"> <div> <p>Name: {item.name}</p> <p>Stock: {item.stock}</p> </div> <button onClick={() => handleDelete(item.id)} className="text-red-500" > Delete </button> </li> ))} </ul> </div> ); }; export default InventoryList;
问题描述
我希望访问/orders/[id]页面时能正常展示订单详情,但现在触发了上面的错误。错误原因是router.query未定义,解构id时抛出TypeError。我已经检查过router.query的值,也确认URL里传了必要的查询参数,但问题还是没解决。不知道在Next.js里router.query为什么会未定义,求排查和修复的建议。
解答
核心问题分析
- App Router路由参数获取方式错误:你用的是Next.js 13+的App Router(
app/目录结构),但next/navigation的useRouter不再提供query属性,动态路由参数得用useParams钩子获取。 - 订单列表页链接错误:
orders/page.js里的Link写了orders.id,但orders是数组,没有id属性,导致生成的链接是/orders/undefined,进一步引发参数问题。
修复步骤
1. 修改订单详情页([id]/page.js)
替换useRouter为useParams来获取动态路由参数:
"use client"; // 导入useParams替代useRouter import { useParams } from "next/navigation"; import { data } from "../../../utils/data"; const OrderDetails = () => { const params = useParams(); const id = params.id; if (!id) { return <div>No order ID provided</div>; } const order = data.orders.find(order => order.id === parseInt(id)); if (!order) { return <div>Order not found</div>; } return ( <div className="container mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">Order Details - {order.id}</h1> <p>Customer: {order.customer}</p> <p>Status: {order.status}</p> <h2 className="text-xl font-semibold ">Items: </h2> <ul> { order.items.map(item => ( <li key={item.id} className="border-b py-2"> <p>Name: {item.name}</p> <p>Quantity: {item.quantity}</p> <p>Stock: {data.items.find(i => i.id === item.id).stock}</p> </li> )) } </ul> <button className="mt-4 bg-green-500 text-white px-4 py-2 rounded">Mark as Completed</button> </div> ); }; export default OrderDetails;
2. 修复订单列表页的链接(orders/page.js)
把orders.id改成当前遍历项的order.id:
<Link href={`/orders/${order.id}`}> <button className="text-blue-500">View Details</button> </Link>
3. 可选优化:处理加载状态
如果需要更严谨的体验,可以在参数未加载时显示加载提示:
if (!id) { return <div>Loading...</div>; }
关键区别说明
Next.js 13+的App Router和旧Pages Router的API逻辑不同:
- Pages Router里
useRouter()返回的对象包含query属性,用来获取路由参数和查询参数 - App Router里,动态路由参数用
useParams()获取,URL查询参数用useSearchParams(),next/navigation的useRouter不再提供query字段
内容的提问来源于stack exchange,提问作者pf4a
相关产品推荐
相关产品推荐

