嵌套模态框下点击浏览器返回按钮关闭多模态框的问题求助
解决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处理,避免重复的路由操作
测试效果
- 点击打开modal1,URL添加
#modal1 - 在modal1内点击打开modal2,URL更新为
#modal2 - 点击浏览器返回按钮:仅modal2关闭,URL回到
#modal1 - 再次点击返回按钮:modal1关闭,哈希从URL中移除
内容的提问来源于stack exchange,提问作者Ali Ehyaie
相关产品推荐
相关产品推荐

