React遍历渲染列表点击触发Popup仅显示数组最后一项数据如何解决
问题根因
所有循环生成的Popup组件共享了同一个布尔类型的显示状态ButtonPopup。当你点击任意按钮把状态设为true时,所有列表项对应的Popup都会同时触发显示,渲染层级靠后的最后一项Popup会覆盖在其他Popup上层,所以你只能看到最后一项的数据。
修复方案
把全局布尔状态替换为存储当前点击项的唯一ID,通过ID匹配控制对应Popup的显示:
- 替换原布尔状态为存储激活项ID的状态,初始值设为
null - 点击按钮时将当前项的ID赋值给状态变量
- 每个Popup的触发条件改为判断当前项ID是否与状态中存储的激活ID一致
- 关闭弹窗时将状态重置为
null即可
修改后业务代码
const HashCode = () => { const [redvalue, setRedValue] = useState(Data); // 替换原布尔状态,存储当前激活弹窗对应的项ID,初始为null const [activeId, setActiveId] = useState(null); return ( <Wrap> <Home code={"Hash Code"} link={"/"} link2={"/RGBCode"} link3={"/Gradients"} link4={"/TwoColorCombination"} /> <Content> {redvalue.map((element, index) => { return ( // 建议把key从index换成唯一的id,避免数组变动时出现渲染异常 <div key={element.id}> <Button type="button" style={{ background: `${element.HEXCode}` }} // 点击时传入当前项的id onClick={() => setActiveId(element.id)} > {element.HEXCode} </Button> <Popup // 只有当前项id等于激活id时才显示弹窗 trigger={activeId === element.id} // 关闭时重置激活id为null setTrigger={setActiveId} > <CopyToClipboard text={element.HEXCode}> <button type="btn">{element.HEXCode}</button> </CopyToClipboard> <CopyToClipboard text={element.RGBACode}> <button type="btn">{element.RGBACode}</button> </CopyToClipboard> </Popup> </div> ); })} </Content> </Wrap> ); }; export default HashCode;
原有Popup组件不需要做任何修改,可以直接复用。
可选优化方案
如果列表项逻辑比较复杂,也可以把单个颜色项抽成独立子组件,每个子组件内部维护自己的Popup显示状态,不需要全局管理激活ID,同样可以解决该问题。
内容的提问来源于stack exchange,提问作者Rahul Singh
相关产品推荐
相关产品推荐

