如何使用多个React-Bootstrap模态框?解决弹窗数据重复问题
解决React-Bootstrap动态生成模态框数据显示错误问题
问题场景
通过映射数组数据生成多个React-Bootstrap模态框,但点击任意弹窗后,所有模态框均显示数组最后一项的数据,需要实现每个弹窗展示对应项的不同数据。
问题原因
- 状态共享冲突:所有模态框共用同一个
modalShow布尔状态,当状态切换为true时,所有模态框都会同时显示;再加上循环闭包特性,最终所有模态框的props都会绑定到数组最后一项的数据。 - 混用原生Bootstrap属性:按钮上添加了
data-bs-toggle和data-bs-target这类Bootstrap原生模态框触发属性,和React的状态管理逻辑冲突,干扰了模态框的正确渲染。
解决方案
方案一:用唯一标识控制单个模态框显示
将全局布尔状态改为存储当前激活模态框的唯一标识(比如数组项中的mod字段),精准控制对应模态框的显示:
const Leadershipcard = (prop: props) => { // 存储当前激活模态框的mod值,初始为null表示无弹窗打开 const [activeModal, setActiveModal] = useState<string | null>(null) return ( <> {content.map((e) => <div className="card col-lg-6 p-0" style={{ "width": "18rem" } as React.CSSProperties} key={e.mod}> <img src={`Assets\\About\\team\\${e.cardimg}.webp`} className="card-img-top" alt={`${e.Name}的照片`} /> <div className="card-body"> <h5 className="card-title">{e.Name}</h5> <p className="card-text">{e.Post}</p> <a href="/" className="d-block fs-4"><i className="fa-brands fa-linkedin-in"></i></a> <button className="btn btn-outline-dark btn-dark rounded-0 text-bg-light mt-2 vi-more" onClick={() => setActiveModal(e.mod)} >查看更多</button> <Modals show={activeModal === e.mod} onHide={() => setActiveModal(null)} Img={e.cardimg} Name={e.Name} Post={e.Post} Nation={e.Nation} About={e.About} mod={e.mod} /> </div> </div> )} </> ) } export default Leadershipcard
修改说明:
- 用
activeModal存储当前要打开的模态框唯一标识,替代原来的布尔状态,实现精准控制。 - 移除按钮上的
data-bs-toggle和data-bs-target属性,完全由React状态管理模态框显示。 - 模态框的
show属性通过判断activeModal是否等于当前项的mod来决定是否显示。 - 为列表项添加
key属性,符合React列表渲染的性能优化要求。
方案二:抽离独立子组件
将每个卡片与对应的模态框封装成独立子组件,使每个组件拥有专属的状态,避免状态共享问题:
// 独立子组件:单个领导卡片+模态框 const LeadershipItem = ({ item }: { item: typeof content[0] }) => { const [modalShow, setModalShow] = useState(false) return ( <div className="card col-lg-6 p-0" style={{ "width": "18rem" } as React.CSSProperties}> <img src={`Assets\\About\\team\\${item.cardimg}.webp`} className="card-img-top" alt={`${item.Name}的照片`} /> <div className="card-body"> <h5 className="card-title">{item.Name}</h5> <p className="card-text">{item.Post}</p> <a href="/" className="d-block fs-4"><i className="fa-brands fa-linkedin-in"></i></a> <button className="btn btn-outline-dark btn-dark rounded-0 text-bg-light mt-2 vi-more" onClick={() => setModalShow(true)} >查看更多</button> <Modals show={modalShow} onHide={() => setModalShow(false)} Img={item.cardimg} Name={item.Name} Post={item.Post} Nation={item.Nation} About={item.About} mod={item.mod} /> </div> </div> ) } // 原父组件 const Leadershipcard = (prop: props) => { return ( <> {content.map((e) => <LeadershipItem key={e.mod} item={e} />)} </> ) } export default Leadershipcard
优势:
- 每个子组件拥有独立的
modalShow状态,互不干扰,彻底解决状态共享导致的数据错误。 - 代码结构更清晰,符合React组件拆分的最佳实践,便于后续维护和扩展。
内容的提问来源于stack exchange,提问作者Nakul Soral
相关产品推荐
相关产品推荐

