React卡片点击触发对应模态框展示专属数据问题求助
解决React卡片模态框点击时全部弹出的问题
原代码的问题在于用单个布尔值modal控制所有卡片的模态框显示,只要modal为true,所有卡片里的模态框都会被渲染。要实现只显示对应卡片的详情,需要跟踪当前选中的工单,而不是用统一的开关。
修改方案
- 调整状态变量:把原来的
modal布尔值改成selectedJob,用来存储当前点击的工单数据,初始值为null。 - 更新模态框触发逻辑:点击"View Details"时,把对应的工单数据传入
toggleModal函数,设置为当前选中的工单;点击关闭或遮罩层时,清空选中的工单。 - 统一模态框渲染:把模态框从卡片循环中移出来,只渲染一个,根据
selectedJob是否存在来控制显示,并展示选中工单的数据。
修改后的完整代码
function ActiveJobs() { const [cards] = React.useState([ { title: "Customer Name: Smith, James", jobnum: "Job Number: 1829", crewnum: "Crew: 0/2", address: "1825 Olive Ave", }, { title: "Customer Name: Cherry, John", jobnum: "Job Number: 8421", crewnum: "Crew: 0/3", address: "256 Milwood Sq", }, { title: "Customer Name: Rudd, Paul", jobnum: "Job Number: 0281", crewnum: "Crew: 0/4", address: "4272 Lowes Island Blvd", }, { title: "Customer Name: Robbie, Margot", jobnum: "Job Number: 2516", crewnum: "Crew: 0/3", address: "265 Atlas Lane", }, { title: "Customer Name: Bond, James", jobnum: "Job Number: 0420", crewnum: "Crew: 0/5", address: "1418 10th Ave", }, { title: "Customer Name: Jordan, Micheal", jobnum: "Job Number: 7617", crewnum: "Crew: 0/10", address: "180 Goat Dr", }, ]); // 用selectedJob存储当前选中的工单,初始为null const [selectedJob, setSelectedJob] = React.useState(null); // 切换模态框:传入job参数,设置选中或清空 const toggleModal = (job) => { // 如果当前选中的就是这个job,就清空(关闭);否则选中这个job setSelectedJob(selectedJob === job ? null : job); }; // 根据是否有选中的工单来控制body的class React.useEffect(() => { if (selectedJob) { document.body.classList.add("active-modal"); } else { document.body.classList.remove("active-modal"); } // 组件卸载时移除class,避免残留 return () => { document.body.classList.remove("active-modal"); }; }, [selectedJob]); // 依赖selectedJob变化触发 return ( <div> <section> <div className="container"> <h1>All Active Jobs</h1> <div className="cards"> {cards.map((card, i) => ( <div key={i} className="card"> <h3>{card.title}</h3> <p>{card.jobnum}</p> <p>{card.crewnum}</p> <p>{card.address}</p> {/* 点击时传入当前card数据 */} <button className="cardbtn" onClick={() => toggleModal(card)}> View Details </button> <button className="cardbtn">Assign Crew</button> </div> ))} </div> </div> </section> {/* 模态框移到循环外,只渲染一个 */} {selectedJob && ( <div className="modal"> <div onClick={() => toggleModal(null)} className="overlay"></div> <div className="modal-content"> <h2>Job Details</h2> <p>{selectedJob.title}</p> <p>{selectedJob.jobnum}</p> <p>{selectedJob.crewnum}</p> <p>{selectedJob.address}</p> <button className="close-modal" onClick={() => toggleModal(null)}> CLOSE </button> </div> </div> )} </div> ); } ReactDOM.createRoot( document.getElementById("root") ).render( <ActiveJobs /> );
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
关键修改说明
- 状态变更:用
selectedJob替代modal,从布尔值变成存储具体工单对象,精准控制要显示的内容。 - 触发逻辑:点击按钮时把当前卡片的
card对象传给toggleModal,判断是否要选中或关闭模态框。 - 模态框位置:把模态框放在循环外面,避免重复渲染多个模态框,提升性能且逻辑更清晰。
- useEffect优化:用
useEffect处理body的class,同时添加清理函数,避免组件卸载后class残留。
内容的提问来源于stack exchange,提问作者qcrx
相关产品推荐
相关产品推荐

