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

Next.js基于路由查询参数渲染带数据模态框时显示数据错误问题

故障根因

问题的核心原因是全局路由参数触发了所有卡片的模态框同时渲染,后渲染的最后一张卡片模态框层级最高,覆盖了所有下层模态框:

  • 每张Card组件内部都自带了一个Modal组件,原本用组件内部状态控制显隐时,只有被点击的Card对应的Modal才会打开,因此数据显示正常。
  • 改为路由参数控制显隐后,你使用的判断条件!!router.query.postId是全局共享的路由状态,只要URL里存在postId参数,所有遍历生成的Card里的Modal都会被标记为打开状态。
  • 模态框默认遵循后渲染层级更高的规则,遍历的最后一条数据对应的Modal会叠加在所有其他Modal之上,因此无论点击哪张卡片,看到的永远是最后一条的内容。
修复方案

方案1:修改模态框显隐判断逻辑(改动最小)

给Card里的Modal的isOpen属性增加id匹配判断,只有路由的postId和当前卡片的id一致时才打开:

const Card = ({ data }) => {
  const router = useRouter();
  return (
    <>
      <Link href={`/?postId=${data._id}`} as={`/view-post/${data.name}`}>
        <h1>{data.name}</h1>
      </Link>
      <Modal
        // 仅打开和路由参数匹配的当前卡片模态框
        isOpen={router.query.postId === data._id}
        onRequestClose={() => router.push("/")}
        contentLabel="Post modal"
      >
        <ModalContent data={data} />
      </Modal>
    </>
  );
};

方案2:抽取模态框到外层(更规范)

避免每个卡片都挂载一个模态框,把模态框移到Feed组件外层,通过路由id匹配对应的数据渲染,性能更优:

// 首页Feed组件
export default function IndexPage() {
  const router = useRouter();
  const data = [
    {
      _id: "x1",
      name: "name_1",
      icon: "url1",
      price: "18"
    },
    {
      _id: "x2",
      name: "name_2",
      icon: "url2",
      price: "27"
    },
    {
      _id: "x3",
      name: "name_3",
      icon: "url3",
      price: "37"
    },
    {
      _id: "x4",
      name: "name_4",
      icon: "url4",
      price: "25"
    }
  ];
  // 匹配当前路由id对应的数据
  const activePost = data.find(item => item._id === router.query.postId);

  return (
    <div>
      {data.map((item) => (
        <Card key={item._id} data={item} />
      ))}
      {/* 全局统一的模态框 */}
      {activePost && (
        <Modal
          isOpen={!!activePost}
          onRequestClose={() => router.push("/")}
          contentLabel="Post modal"
        >
          <ModalContent data={activePost} />
        </Modal>
      )}
    </div>
  );
}

// Card组件只保留Link,无需再内置Modal
const Card = ({ data }) => {
  return (
    <Link href={`/?postId=${data._id}`} as={`/view-post/${data.name}`}>
      <h1>{data.name}</h1>
    </Link>
  )
}

内容的提问来源于stack exchange,提问作者Ray Purchase

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 11:06:03