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

ReactJS循环中Bootstrap模态框子组件传值异常问题

问题原因分析

1. Bootstrap模态框ID冲突

原生Bootstrap的模态框通过id属性关联触发按钮与模态框。如果循环渲染时,所有Component1内的模态框都使用相同的固定id(比如exampleModal),点击任何触发按钮都会匹配DOM中第一个带该id的模态框,自然只会显示第一个循环项的数据。

2. 不必要的useState存储props引发状态不同步

你在Component1和MainbodyComp2中将传入的props存入useState的操作完全多余,还会加剧问题:

  • 组件初始化时,useState会用初始props值固定状态。循环渲染时,由于闭包或渲染批次特性,子组件可能未正确捕获当前循环项的props,反而拿到第一个项的值。
  • 即使后续props更新,useState不会自动同步状态,除非手动添加useEffect监听,但这属于画蛇添足的操作。
可行解决方案

方案一:给每个模态框生成唯一ID(原生Bootstrap)

利用循环项的唯一标识(比如数据的id字段)为每个模态框和触发按钮生成独特id,同时去掉不必要的useState存储,直接使用props传递数据。

父组件代码

function ParentComponent() {
  // 示例数据,每个item需包含唯一id
  const items = [
    { id: 1, name: "项目1", desc: "这是项目1的详情" },
    { id: 2, name: "项目2", desc: "这是项目2的详情" }
  ];

  return (
    <div className="container mt-3">
      {items.map(item => (
        <Component1 key={item.id} item={item} />
      ))}
    </div>
  );
}

Component1代码

function Component1({ item }) {
  // 基于item.id生成唯一模态框ID
  const modalId = `detail-modal-${item.id}`;

  return (
    <div className="mb-2">
      {/* 触发按钮绑定对应模态框的ID */}
      <button
        type="button"
        className="btn btn-primary"
        data-bs-toggle="modal"
        data-bs-target={`#${modalId}`}
      >
        查看{item.name}详情
      </button>

      {/* 模态框使用唯一ID */}
      <div
        className="modal fade"
        id={modalId}
        tabIndex="-1"
        aria-labelledby={`${modalId}-title`}
        aria-hidden="true"
      >
        <div className="modal-dialog">
          <div className="modal-content">
            <MainbodyComp2 item={item} />
          </div>
        </div>
      </div>
    </div>
  );
}

MainbodyComp2代码

function MainbodyComp2({ item }) {
  const modalTitleId = `detail-modal-${item.id}-title`;
  
  return (
    <>
      <div className="modal-header">
        <h5 className="modal-title" id={modalTitleId}>
          {item.name}
        </h5>
        <button
          type="button"
          className="btn-close"
          data-bs-dismiss="modal"
          aria-label="Close"
        ></button>
      </div>
      <div className="modal-body">
        <p>{item.desc}</p>
      </div>
      <div className="modal-footer">
        <button
          type="button"
          className="btn btn-secondary"
          data-bs-dismiss="modal"
        >
          关闭
        </button>
      </div>
    </>
  );
}

方案二:使用React Bootstrap的受控模态框(更推荐)

如果项目使用React Bootstrap库,可通过受控组件方式,只渲染一个模态框,用状态控制显示内容,彻底避免ID冲突,代码更简洁高效。

示例代码

import { useState } from 'react';
import { Button, Modal } from 'react-bootstrap';

function ParentComponent() {
  const items = [
    { id: 1, name: "项目1", desc: "这是项目1的详情" },
    { id: 2, name: "项目2", desc: "这是项目2的详情" }
  ];

  const [showModal, setShowModal] = useState(false);
  const [currentItem, setCurrentItem] = useState(null);

  // 打开模态框时传入当前点击的item
  const handleOpenModal = (item) => {
    setCurrentItem(item);
    setShowModal(true);
  };

  return (
    <div className="container mt-3">
      {items.map(item => (
        <Button
          key={item.id}
          className="mb-2 me-2"
          onClick={() => handleOpenModal(item)}
        >
          查看{item.name}详情
        </Button>
      ))}

      {/* 唯一的模态框,通过state控制显示和内容 */}
      <Modal show={showModal} onHide={() => setShowModal(false)}>
        <Modal.Header closeButton>
          <Modal.Title>{currentItem?.name}</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          {currentItem?.desc}
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={() => setShowModal(false)}>
            关闭
          </Button>
        </Modal.Footer>
      </Modal>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Elon Musk On Stackoverflow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:57:51