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
相关产品推荐
相关产品推荐

