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

嵌套模态框下点击浏览器返回按钮关闭多模态框的问题求助

解决Next.js多模态框返回按钮同时关闭问题

问题根源

每个Modal组件在打开时都会给window注册popstate事件监听,当浏览器触发返回操作时,所有已注册的回调函数都会执行,导致所有打开的Modal同时关闭。

解决方案

修改Modal组件的事件监听逻辑,仅当当前URL哈希与组件指定的哈希匹配时,才执行关闭操作。同时优化路由和事件解绑逻辑,避免冗余操作。

修改后的Modal组件代码

import React, { useEffect } from 'react';
import { useRouter } from "next/router";

const Modal = ({ isOpen, children, onClose, hash }) => {
    const router = useRouter();

    useEffect(() => {
        const handlePopState = () => {
            // 仅当当前哈希与组件哈希匹配时,才执行关闭
            if (window.location.hash === hash) {
                onClose();
            }
        };

        if (isOpen) {
            // 仅当当前哈希不匹配时才跳转,避免重复添加
            if (window.location.hash !== hash) {
                router.push(hash);
            }
            window.addEventListener('popstate', handlePopState);
            return () => {
                window.removeEventListener('popstate', handlePopState);
            };
        } else {
            // 关闭时如果当前哈希匹配,移除哈希
            if (window.location.hash === hash) {
                router.replace('/', undefined, { shallow: true });
            }
        }
    }, [isOpen, hash, onClose, router]);

    return (
        isOpen && <div style={{
            background: 'white',
            position: 'fixed',
            top: '0',
            left: '0',
            width: '100vw',
            height: '100vh',
            display: 'flex',
            flexDirection: 'column',
            gap: '10px',
            padding: '20px'
        }}>
            <span
                onClick={() => {
                    onClose();
                }}
                style={{
                    background: 'coral',
                    borderRadius: '10px',
                    alignSelf: 'center',
                    cursor: 'pointer',
                    padding: '8px 16px'
                }}>Close Modal</span>
            {children}
        </div>
    );
};

export default Modal;

关键修改点

  • 哈希匹配判断:在popstate回调中增加window.location.hash === hash的判断,确保只有对应哈希的Modal才会响应返回事件
  • 避免重复路由跳转:打开Modal时先检查当前哈希是否一致,不一致才执行router.push
  • 关闭时清理哈希:Modal关闭时如果当前哈希匹配,用router.replace移除哈希(使用shallow: true避免页面重新渲染)
  • 简化关闭按钮逻辑:关闭按钮只需调用onClose,哈希清理交给useEffect处理,避免重复的路由操作

测试效果

  1. 点击打开modal1,URL添加#modal1
  2. 在modal1内点击打开modal2,URL更新为#modal2
  3. 点击浏览器返回按钮:仅modal2关闭,URL回到#modal1
  4. 再次点击返回按钮:modal1关闭,哈希从URL中移除

内容的提问来源于stack exchange,提问作者Ali Ehyaie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:02:45