Next.js 14如何通过路由传参?保持URL为商品名称
解决方案
方案一:通过商品名称(Slug)在服务器端反查ID(推荐)
这是最稳妥的实现方式,URL中的商品名称(slug)本身就应该和商品一一对应,直接在目标页面的服务器组件里用slug查询数据库获取ID即可,无需额外传递:
- 将路由文件夹重命名为
app/items/[slug]/page.js(把之前的[itemId]改成[slug]更语义化) - 商品列表页面跳转时,直接用处理后的商品标题作为slug:
'use client'; import { useRouter } from 'next/navigation'; // 商品列表项组件 const ItemCard = ({ item }) => { const router = useRouter(); // 处理标题为URL安全格式,避免特殊字符导致路由错误 const safeTitle = encodeURIComponent(item.title); return ( <div onClick={() => router.push(`/items/${safeTitle}`)}> {/* 商品内容渲染 */} </div> ); };
- 在
app/items/[slug]/page.js服务器组件中,通过params.slug查询商品ID:
// 服务器组件,无需添加'use client'指令 export default async function ItemPage({ params }) { // 解码URL中的slug,还原原始标题 const originalTitle = decodeURIComponent(params.slug); // 根据标题从数据库/API查询商品详情(包含ID) const item = await fetch(`https://your-api.com/items?title=${originalTitle}`).then(res => res.json()); // 拿到ID后发起后续业务请求 const relatedData = await fetch(`https://your-api.com/related/${item.id}`).then(res => res.json()); return ( <div> <h1>{item.title}</h1> {/* 商品详情及关联内容渲染 */} </div> ); }
方案二:通过导航State传递ID(客户端临时传递,不暴露URL)
如果必须在客户端直接传递ID,Next.js 14的useRouter支持跳转时传递state参数,该数据不会出现在URL中,仅在客户端导航流程中保留:
- 列表页面跳转时,附带state传递ID:
'use client'; import { useRouter } from 'next/navigation'; const ItemCard = ({ item }) => { const router = useRouter(); const safeTitle = encodeURIComponent(item.title); return ( <div onClick={() => { router.push(`/items/${safeTitle}`, { state: { itemId: item.id } }); }} > {/* 商品内容渲染 */} </div> ); };
- 在目标页面的客户端组件中,从路由state中获取ID:
'use client'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; export default function ItemPage() { const router = useRouter(); const [itemData, setItemData] = useState(null); useEffect(() => { // 从导航state中提取ID const navState = router.state; if (navState?.itemId) { // 用ID发起请求获取商品数据 fetch(`https://your-api.com/items/${navState.itemId}`) .then(res => res.json()) .then(data => setItemData(data)); } }, [router]); if (!itemData) return <div>Loading...</div>; return ( <div> <h1>{itemData.title}</h1> {/* 商品详情渲染 */} </div> ); }
注意:这种方式的state仅在客户端跳转时有效,如果用户直接刷新页面或通过URL访问,state会丢失,因此仅适合临时数据传递,优先推荐方案一。
内容的提问来源于stack exchange,提问作者andorando
相关产品推荐
相关产品推荐

