You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:27:31