You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React卡片点击触发对应模态框展示专属数据问题求助

解决React卡片模态框点击时全部弹出的问题

原代码的问题在于用单个布尔值modal控制所有卡片的模态框显示,只要modal为true,所有卡片里的模态框都会被渲染。要实现只显示对应卡片的详情,需要跟踪当前选中的工单,而不是用统一的开关。

修改方案

  1. 调整状态变量:把原来的modal布尔值改成selectedJob,用来存储当前点击的工单数据,初始值为null。
  2. 更新模态框触发逻辑:点击"View Details"时,把对应的工单数据传入toggleModal函数,设置为当前选中的工单;点击关闭或遮罩层时,清空选中的工单。
  3. 统一模态框渲染:把模态框从卡片循环中移出来,只渲染一个,根据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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:35:05