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

React项目中Bootstrap模态框的hidden.bs.modal事件不触发怎么解决?

问题根因

  • 事件绑定时机错误:你将$('#exampleModal').on('hidden.bs.modal')直接写在函数组件顶层,组件执行渲染逻辑时模态框DOM还未挂载到页面,jQuery无法匹配到对应元素,事件绑定失效。
  • 两套显隐逻辑冲突:你同时使用了Bootstrap原生的data-toggle属性触发模态框,又用React的productImageHandler状态控制模态框的条件渲染,逻辑不同步导致原生事件无法正常触发。
  • 组件直接卸载截断事件:你点击关闭按钮后直接将productImageHandler设为false,模态框DOM会被立刻从页面移除,Bootstrap的关闭动画还未执行完,hidden.bs.modal事件根本没有触发机会。

修复方案

第一步:修改Modal.js代码

使用useEffect保证DOM挂载后再绑定事件,同时关联Bootstrap原生模态框方法和你的关闭逻辑:

import React, { useEffect } from 'react';
import $ from 'jquery';

const Modal = (props) => {
  // 组件挂载后初始化模态框、绑定事件
  useEffect(() => {
    const $modal = $('#exampleModal');
    // 初始化模态框,配置点击背景关闭
    $modal.modal({
      backdrop: true, // 允许点击背景关闭
      show: true // 挂载后直接显示
    });
    // 绑定关闭完成事件
    $modal.on('hidden.bs.modal', (e) => {
      console.log('模态框已关闭', e);
      props.onClose(false);
    });
    // 组件卸载前清理事件、销毁模态框实例
    return () => {
      $modal.off('hidden.bs.modal');
      $modal.modal('dispose');
    };
  }, [props]);

  function onClickHandler(e) {
    fetch(
      'http://reactapi.test/api/product/delete/' +
        e.target.attributes.guid.value,
      {
        method: 'get',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
      }
    )
      .then((response) => response.json())
      .then((data) => {
        console.log(data);
      });
  }
  function onModalDismissEvent(e) {
    // 调用Bootstrap原生关闭方法,会自动触发hidden.bs.modal事件
    $('#exampleModal').modal('hide');
  }

  return (
    <div
      className='modal fade'
      id='exampleModal'
      tabIndex='-1'
      aria-labelledby='exampleModalLabel'
      aria-hidden='true'
    >
      <div className='modal-dialog'>
        <div className='modal-content'>
          <div className='modal-header'>
            <h5 className='modal-title' id='exampleModalLabel'>
              Resimler
            </h5>
            <button
              type='button'
              className='close'
              data-dismiss='modal'
              aria-label='Close'
              onClick={onModalDismissEvent}
            >
              <span aria-hidden='true'>&times;</span>
            </button>
          </div>
          <div className='modal-body'>
            {props.product.slider.map((e) => {
              return (
                <div key={e.products_slider_guid}>
                  <img
                    height='150px'
                    src={'http://example.test/' + e.image}
                    alt={e.created_at}
                  />
                  <button className='btn btn-outline-primary mr-2'>
                    Update
                  </button>
                  <button
                    onClick={onClickHandler}
                    className='btn btn-outline-danger mr-2'
                    guid={e.products_slider_guid}
                  >
                    Delete
                  </button>
                </div>
              );
            })}
          </div>
          <div className='modal-footer'>
            <button className='btn btn-outline-primary mr-4' type='button'>
              Save
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Modal;

第二步:修改Main.js代码

删除触发按钮上的Bootstrap原生控制属性,避免和React状态逻辑冲突:

import React, { useContext, useState } from 'react';
import ProductContext from '../store/product-context';
import Modal from './Modal';
const Main = (props) => {
  const [productImageHandler, setProductImageHandler] = useState(false);
  const [findProductHandler, setFindProductHandler] = useState('');
  const productCtx = useContext(ProductContext);

  const onClickHandler = (event) => {
    const findProduct = productCtx.items.find((item) => {
      return item.product_guid === event.target.attributes.guid.value;
    });
    setFindProductHandler(findProduct);
    setProductImageHandler(true);
  };
  const onCloseHandler = (e) => {
    setProductImageHandler(e);
  };

  return (
    <div>
      <main ref={(modal) => modal} role='main' className='container mt-5'>
        <div className='row'>
          <div className='col-xl-12'>
            {productCtx.items.map((item) => {
              return (
                <div key={item.id} className='list-group'>
                  <div className='list-group-item d-flex justify-content-between align-items-center'>
                    {item.name}
                    <div>
                      <button
                        className='btn btn-outline-info mr-2'
                        // 删除原有的data-toggle和data-target属性
                        onClick={onClickHandler}
                        guid={item.product_guid}
                      >
                        Images
                      </button>

                      <button className='btn btn-outline-danger mr-2'>
                        Delete
                      </button>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
        {productImageHandler && (
          <Modal onClose={onCloseHandler} product={findProductHandler} />
        )}
      </main>
    </div>
  );
};

export default Main;

修改后点击模态框背景、右上角关闭按钮都会触发hidden.bs.modal事件,且会同步更新React的显隐状态,逻辑完全对齐。


内容的提问来源于stack exchange,提问作者Okay Beydanol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:48:03