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

Next.js Router Query数据异常:videos字段出现空字符串求助

Next.js中通过Link传递分类数据后videos字段为空字符串数组的问题

问题场景

我在Next.js项目中从Context API获取所有分类数据展示在首页,通过next/link跳转到分类详情页面[category_slug].jsx。跳转代码如下:

categories.map((category) => (
  <Link
    href={{ pathname: `/categories/${category.category_slug}`, query: category }}
    className="text-sm hover:underline hover:opacity-60"
    key={category.id}
  >
    {category.name}
  </Link>
))

此前用相同方式实现视频页面时功能正常,但本次跳转后,分类详情页面能正常获取其他字段,唯独videos字段返回["", ""],不符合预期。接收的数据示例:

{
    "id": "9",
    "name": "test2",
    "category_slug": "test2",
    "description": "testt2",
    "videos": [
        "",
        ""
    ],
    "image": "",
    "created": "2022-12-07T02:07:05.838815Z",
    "updated": "2022-12-07T02:07:05.838840Z"
}

分类详情页面代码:

import React from "react";

const CategoryPage = () => {
    const router = useRouter()
    const category = router.query;

    console.log(category)

  // captilaze first letter and lowercase the rest
  const capitalize = (s) => {
    if (typeof s !== "string") return "";
    return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();

  };
  return (
    <>

    {  /* <CustomHead title={capitalize(category.name)} />*/}
      <div className="my-10 mx-auto flex min-h-screen  px-24   py-10  ">
        <div className="flex w-full flex-col bg-white p-10">
            { /* <h1 className="text-2xl font-bold up capitalize">{category.name}</h1>*/}
          <div className="mt-10 grid grid-cols-1 place-items-center  gap-2 md:grid-cols-3">
          </div>
        </div>
      </div>
    </>
  );
};

export default CategoryPage;

问题原因

Next.js的Link组件在传递query参数时,会对数据进行URL序列化。如果videos字段原本是对象数组或包含复杂结构的数据,序列化过程中会丢失信息,最终变成空字符串数组。而你之前的视频页面可能传递的是简单字符串或结构更简单的对象,所以没有出现该问题。

另外,直接通过query传递完整对象并非最佳实践,不仅有URL长度限制,还可能引发序列化/反序列化异常。

解决方案

方案1:仅传递slug,在详情页重新请求数据(推荐)

放弃直接传递完整分类对象,只通过路径参数传递category_slug,然后在详情页调用后端接口获取完整分类数据:

首页跳转代码修改:

categories.map((category) => (
  <Link
    href={`/categories/${category.category_slug}`}
    className="text-sm hover:underline hover:opacity-60"
    key={category.id}
  >
    {category.name}
  </Link>
))

分类详情页[category_slug].jsx修改:

import React, { useEffect, useState } from "react";
import { useRouter } from 'next/router';

const CategoryPage = () => {
  const router = useRouter();
  const [category, setCategory] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 确保router参数已加载完成
    if (router.isReady && router.query.category_slug) {
      fetch(`/api/categories/${router.query.category_slug}`)
        .then(res => res.json())
        .then(data => {
          setCategory(data);
          setLoading(false);
        })
        .catch(err => {
          console.error('获取分类数据失败:', err);
          setLoading(false);
        });
    }
  }, [router.isReady, router.query.category_slug]);

  if (loading) return <div className="px-24 py-10">加载中...</div>;
  if (!category) return <div className="px-24 py-10">分类不存在</div>;

  const capitalize = (s) => {
    if (typeof s !== "string") return "";
    return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
  };

  return (
    <>
      <div className="my-10 mx-auto flex min-h-screen px-24 py-10">
        <div className="flex w-full flex-col bg-white p-10">
          <h1 className="text-2xl font-bold up capitalize">{category.name}</h1>
          <div className="mt-10 grid grid-cols-1 place-items-center gap-2 md:grid-cols-3">
            {/* 渲染videos列表 */}
            {category.videos.length > 0 ? (
              category.videos.map((video, idx) => (
                <div key={idx} className="p-4 border rounded">
                  {video}
                </div>
              ))
            ) : (
              <p>暂无视频</p>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

export default CategoryPage;

方案2:手动序列化/反序列化数据(不推荐)

如果必须通过query传递完整对象,可以手动将数据序列化为JSON字符串,在详情页再解析:

首页跳转代码修改:

categories.map((category) => (
  <Link
    href={{
      pathname: `/categories/${category.category_slug}`,
      query: { category: JSON.stringify(category) }
    }}
    className="text-sm hover:underline hover:opacity-60"
    key={category.id}
  >
    {category.name}
  </Link>
))

分类详情页解析数据:

import React from "react";
import { useRouter } from 'next/router';

const CategoryPage = () => {
  const router = useRouter();
  // 解析序列化后的分类数据
  const category = router.query.category ? JSON.parse(router.query.category) : null;

  if (!category) return <div>加载中...</div>;

  const capitalize = (s) => {
    if (typeof s !== "string") return "";
    return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
  };

  return (
    <>
      <div className="my-10 mx-auto flex min-h-screen px-24 py-10">
        <div className="flex w-full flex-col bg-white p-10">
          <h1 className="text-2xl font-bold up capitalize">{category.name}</h1>
          <div className="mt-10 grid grid-cols-1 place-items-center gap-2 md:grid-cols-3">
            {category.videos.map((video, idx) => (
              <div key={idx}>{video}</div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
};

export default CategoryPage;

注意:该方案存在URL长度限制,若分类数据过大可能导致传递失败,且数据暴露在URL中存在安全风险,因此不推荐使用。

内容的提问来源于stack exchange,提问作者Aliyasir Naç

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:41:42