Next.js动态路由导航传递数据失败,如何解决?
问题分析
你遇到的问题核心有两个:
- 直接传递复杂对象到query参数:URL查询参数仅支持字符串类型,
curElm作为对象会被自动转为[object Object],无法被正确解析传递。 - 未声明客户端组件:在Next.js App Router中,
useSearchParams属于客户端钩子,必须在添加了'use client'指令的组件中使用,否则无法正常工作。
解决方案
方案1:传递商品ID,详情页重新获取数据(推荐)
这是电商应用的标准实现方式,URL更简洁,且页面刷新时也能正常加载数据。
修改发送数据的Link组件
// 假设curElm包含唯一标识字段id <Link href={{ pathname: '/hoodies/[title]', params: { title: curElm.title }, // 规范传递动态路由参数 query: { id: curElm.id } // 仅传递商品ID }}> <div className="shadow cursor-pointer"> <Image src={curElm.images[0]} width={200} height={60} /> <h1 className="font-semibold">{curElm.brand}</h1> <h2>{curElm.title}</h2> <div className="flex gap-2"> <h3 className="font-semibold">Price: {curElm.price}</h3> </div> </div> </Link>
详情页接收并获取数据
'use client'; // 必须添加,否则useSearchParams无法使用 import { useSearchParams } from 'next/navigation'; import { useEffect, useState } from 'react'; // 导入你的Firebase数据获取方法,比如getProductById export default function HoodieDetail() { const searchParams = useSearchParams(); const productId = searchParams.get('id'); const [product, setProduct] = useState(null); useEffect(() => { if (productId) { // 调用Firebase接口获取对应ID的商品数据 const fetchProduct = async () => { const data = await getProductById(productId); setProduct(data); }; fetchProduct(); } }, [productId]); if (!product) return <div>Loading...</div>; return ( <div> <h1>{product.title}</h1> <Image src={product.images[0]} width={400} height={120} /> <p>品牌:{product.brand}</p> <p>价格:{product.price}</p> {/* 渲染更多商品详情 */} </div> ); }
方案2:序列化对象为JSON字符串传递(不推荐)
如果必须直接传递对象,需要先将对象序列化为JSON字符串,详情页再解析。但这种方式会导致URL过长,且敏感数据可能暴露,仅适合非敏感的简单对象。
修改发送数据的Link组件
<Link href={{ pathname: '/hoodies/[title]', params: { title: curElm.title }, query: { name: JSON.stringify(curElm) } // 将对象序列化为JSON字符串 }}> {/* 商品卡片内容 */} </Link>
详情页接收并解析
'use client'; import { useSearchParams } from 'next/navigation'; export default function HoodieDetail() { const searchParams = useSearchParams(); const productStr = searchParams.get('name'); const product = productStr ? JSON.parse(productStr) : null; console.log(product); // 现在可以正常输出商品对象 if (!product) return <div>Loading...</div>; return ( <div> <h1>{product.title}</h1> {/* 渲染商品详情 */} </div> ); }
内容的提问来源于stack exchange,提问作者Vivek Fauzdar
相关产品推荐
相关产品推荐

