React遍历渲染列表时如何匹配点击项数据传参给动态弹窗组件
问题原因
你当前的代码存在两个核心逻辑错误:
- 仅用一个全局的
isOpen布尔值控制弹窗显隐,当这个值为true时,map遍历生成的所有项目卡片内部的Popup组件都会被渲染,视觉上最终只会展示最后一个遍历项的弹窗内容,这就是你点击任意项目都看到相同文本的根本原因。 - 点击回调没有记录当前触发点击的项目对象,无法精准匹配需要展示详情的目标数据。
修复方法
不要用单一布尔值存储弹窗状态,改为直接存储当前选中的项目对象即可:
- 将原有的
isOpen布尔状态替换为选中项目状态,默认值设为null代表弹窗处于关闭状态 - 修改点击事件回调,点击对应项目卡片时,将当前遍历到的项目对象存入状态
- 把Popup组件从
map循环内部移到外层,仅当存在选中项目时渲染弹窗,直接传入选中项目的属性即可 - 补充弹窗关闭逻辑,触发关闭时将选中项目状态重置为
null
修复后的Projects组件代码如下:
function Projects() { // 存储当前选中的项目,默认null为关闭弹窗状态 const [selectedProject, setSelectedProject] = useState(null); return ( <Wrapper> {data.projects.map((proj) => ( <ProjectContainer // 遍历项必须加唯一key,避免React渲染警告 key={proj.name} background={proj.image} onClick={() => setSelectedProject(proj)} > {/* 卡片内部只放项目本身的展示内容,不再放弹窗 */} <h3>{proj.name}</h3> </ProjectContainer> ))} {/* 外层统一渲染弹窗 */} {selectedProject && ( <Popup project={selectedProject.name} description={selectedProject.description} onClose={() => setSelectedProject(null)} /> )} </Wrapper> ); }
你可以在Popup组件内部新增一个关闭按钮,点击时触发传入的onClose回调即可实现弹窗关闭功能。
如果你一定要把弹窗放在对应项目卡片的内部位置,也可以在状态中存储当前选中项目的唯一标识(比如name),渲染时同时判断selectedProject?.name === proj.name才渲染对应卡片内的弹窗,不过将弹窗统一放在外层渲染的逻辑更简洁,也不会重复生成多个冗余的弹窗节点。
内容的提问来源于stack exchange,提问作者TheRobertos
相关产品推荐
相关产品推荐

