React循环中Modal批量弹出问题:如何按ID打开对应弹窗?
问题:循环中的React弹窗点击后全部打开,需按ID打开对应弹窗
问题场景
实现React弹窗后,将Modal置于循环中,点击任意按钮会打开所有弹窗,需要实现点击按钮仅打开对应ID的弹窗。
原代码问题分析
原useModal钩子使用单个布尔值isShown控制所有弹窗的显示状态,循环内的所有Modal都绑定同一个状态,导致点击时所有弹窗同时触发显示。
修改方案
1. 更新useModal钩子
将状态从单个布尔值改为跟踪当前激活的弹窗ID(null表示无弹窗打开):
import { useState } from 'react'; export const useModal = () => { const [activeModalId, setActiveModalId] = useState<string | null>(null); const openModal = (id: string) => setActiveModalId(id); const closeModal = () => setActiveModalId(null); const isModalShown = (id: string) => activeModalId === id; return { openModal, closeModal, isModalShown }; };
2. 修改Alert组件
使用新的useModal方法,给每个按钮绑定对应弹窗的ID,Modal根据ID判断是否显示:
export default function Alert({}: Props) { const { alerts, loading } = useGetAlerts(); const { openModal, closeModal, isModalShown } = useModal(); return ( <div className={styles.alertHeader}> <div className={styles.title}>Alerts</div> <div className={styles.alertFrame}> <div className={styles.counter}>{`${alerts?.items.length}`}</div> <div className={styles.titleFrame}> <div className={styles.summaryTitle}> Outstanding <br></br>Alerts </div> </div> </div> {loading ? ( <SnakeLoader /> ) : ( alerts?.items.slice(0, 5).map((a) => ( <div key={`id_${a.id}`} className={styles.alertFrame}> <div className={styles.titleFrame} id="titleFrame"> <div className={styles.alertTitle} id="alertTitle"> {' '} {`${a.message}`}{' '} </div> <div className={styles.alertLink} id="alertLink"> <button onClick={() => openModal(a.id)}>Click for More</button> <Modal isShown={isModalShown(a.id)} hide={closeModal} modalContent={a.message} headerText={a.id} /> </div> </div> <div className={styles.alertClose} id="alertClose"> X </div> </div> )) )} </div> ); }
3. Modal组件无需修改
原Modal组件逻辑保持不变,它仅负责接收isShown状态和hide方法,现在传入的isShown是针对单个弹窗的判断结果。
核心思路
通过跟踪当前激活的弹窗ID,替代全局布尔状态,让每个Modal独立判断自身是否需要显示,从而实现点击按钮仅打开对应ID的弹窗。
内容的提问来源于stack exchange,提问作者Possam
相关产品推荐
相关产品推荐

