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

Next.js集成Bootstrap 5:手动调用hide()无法关闭模态框的问题

Next.js中Bootstrap 5.2模态框调用hide()无效的问题解决

错误原因

  • 你每次调用hideModal时都重新创建了一个新的Modal实例,而不是使用Bootstrap通过data-bs-toggle打开时已经初始化好的那个实例。新实例和当前显示的模态框没有关联,所以调用hide()不会产生任何效果。
  • 组件内重复require("bootstrap")属于冗余操作,还可能导致实例上下文不统一。

解决方案

方法一:获取Bootstrap已初始化的实例

修改hideModal函数,使用Bootstrap提供的Modal.getOrCreateInstance方法获取当前模态框的实例,而非重新创建:

export function LoginModal() {
    const loginModalRef = useRef();

    const hideModal = () => {
        // 获取已存在的实例,不存在则自动创建
        const myModal = bootstrap.Modal.getOrCreateInstance(loginModalRef.current);
        myModal.hide();
    };

    function sendRequest() {
        // 模拟请求成功逻辑
        hideModal();
    }

    return (
        <>
            <div ref={loginModalRef} id="login-modal" className="modal fade">
                <div className="modal-dialog modal-dialog-centered">
                    <div className="modal-content">
                        <svg className="close-icon position-absolute pointer" data-bs-dismiss="modal">
                            <use xlinkHref="/images/sprite.svg#close-icon"></use>
                        </svg>
                        <div className="modal-body">
                            MyModalContent
                            <div onClick={sendRequest}>Send</div>
                        </div>
                    </div>
                </div>
            </div>
        </>
    );
}

注意:因为你已经在_app.js中引入了bootstrap.bundle.min.js,全局bootstrap对象已可直接使用,无需在组件内重复require。

方法二:用React状态统一控制模态框(推荐)

避免混合使用Bootstrap的data属性和手动JS控制,改用React状态管理模态框的显示隐藏,更符合React的开发思维:

import { useState, useRef, useEffect } from 'react';

export function LoginModal() {
    const loginModalRef = useRef();
    const [showModal, setShowModal] = useState(false);
    let myModal = null;

    useEffect(() => {
        // 初始化模态框实例
        myModal = new bootstrap.Modal(loginModalRef.current);
        // 监听模态框隐藏事件,同步React状态
        loginModalRef.current.addEventListener('hidden.bs.modal', () => {
            setShowModal(false);
        });
        // 组件卸载时销毁实例
        return () => {
            myModal.dispose();
        };
    }, []);

    // 根据状态切换模态框显示/隐藏
    useEffect(() => {
        showModal ? myModal.show() : myModal.hide();
    }, [showModal]);

    const hideModal = () => {
        setShowModal(false);
    };

    function sendRequest() {
        // 模拟请求成功逻辑
        hideModal();
    }

    return (
        <>
            {/* 替换原data-bs-toggle触发按钮,用状态控制打开 */}
            <button onClick={() => setShowModal(true)}>打开登录模态框</button>
            
            <div ref={loginModalRef} className="modal fade">
                <div className="modal-dialog modal-dialog-centered">
                    <div className="modal-content">
                        <svg className="close-icon position-absolute pointer" onClick={() => setShowModal(false)}>
                            <use xlinkHref="/images/sprite.svg#close-icon"></use>
                        </svg>
                        <div className="modal-body">
                            MyModalContent
                            <div onClick={sendRequest}>Send</div>
                        </div>
                    </div>
                </div>
            </div>
        </>
    );
}

这种方式完全通过React状态控制模态框,避免了与Bootstrap自动初始化实例的冲突,逻辑更清晰可控。

内容的提问来源于stack exchange,提问作者Андрей Горев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:13:12