Next.js router.query传递数组返回异常值问题解决
router.query 本质是对URL查询字符串的解析结果,所有参数最终都会被序列化为URL可传输的字符串格式,不支持直接传递嵌套对象、对象数组这类复杂结构化数据。你直接把reviews对象数组传入query时,Next.js内部序列化逻辑会把对象的每个属性拆成独立空键位,最终解析出来就会得到全是空字符串的异常数组,这和router.isReady判断没有关系,加路由就绪逻辑解决不了序列化层面的问题。
额外注意:你贴的目标页面代码里
Reviews组件定义缺少函数体包裹,属于语法错误,记得补上{ return ... },否则编译阶段就会报错。
根据你的数据量和业务场景选一个即可:
方案1:序列化后传字符串(适合数据量小的简单场景)
传参前把复杂数据用JSON.stringify转成JSON字符串,接收的时候再用JSON.parse转回数组即可。
修改父页面跳转逻辑:
{array.map((item) => ( <Grid key={item} item> <Card label={item.title} onClick={() => router.push({ pathname: "/page", query: { title: item.title, reviews: JSON.stringify(item.reviews), // 序列化转字符串 }, }) } /> </Grid> ))}
目标页面接收时做反序列化:
function index() { const router = useRouter(); const [reviewsList, setReviewsList] = useState([]); useEffect(() => { if (!router.isReady) return; // 反序列化拿到原始数组 setReviewsList(JSON.parse(router.query.reviews as string)); }, [router.isReady]); const Reviews = () => { return <ReviewCard reviewsList={reviewsList} />; }; return ( <Box> <Typography>{router.query.title}</Typography> <Reviews /> </Box> ); } export default index;
注意:URL有长度限制(不同浏览器支持范围在2KB-8KB不等),如果reviews数组内容很长不要用这个方案,会出现URL截断导致数据丢失、解析失败。
方案2:客户端缓存传参(适合数据量大、不想走接口的场景)
不需要把完整数据拼在URL上,跳转前把数据存在客户端会话缓存里,目标页面通过唯一标识读取即可,常见实现选择:
- React Context 跨页面状态
- 轻量客户端状态库
- 会话级存储
sessionStorage
以sessionStorage实现为例:
父页面跳转前存数据:
onClick={() => { // 生成唯一id做数据关联,避免多入口跳转时数据混淆 const dataId = crypto.randomUUID(); sessionStorage.setItem(`detail_reviews_${dataId}`, JSON.stringify(item.reviews)); router.push({ pathname: "/page", query: { title: item.title, dataId: dataId, // 只传关联id,不塞大段数据 }, }) }}
目标页面读取缓存:
const [reviewsList, setReviewsList] = useState([]); useEffect(() => { if (!router.isReady) return; const cachedData = sessionStorage.getItem(`detail_reviews_${router.query.dataId}`); if (cachedData) setReviewsList(JSON.parse(cachedData)); // 读完即可清掉缓存,避免不必要的空间占用 sessionStorage.removeItem(`detail_reviews_${router.query.dataId}`); }, [router.isReady]);
方案3:接口拉取数据(生产环境最推荐的规范方案)
列表页跳转时只传递当前条目的唯一标识(比如条目id),目标页面拿到id之后,直接调用后端接口拉取完整的title、reviews等详情数据,完全不需要跨页面传大段数据,也不存在URL长度限制、序列化异常、缓存不一致的问题,长期维护成本最低。
内容的提问来源于stack exchange,提问作者Salvo

