Next.js+Tailwind模态框动画失效且无法从DOM移除问题求助
解决Next.js模态框关闭动画与DOM移除冲突问题
问题分析
当前模态框存在两个核心问题:
- 直接用
isOpen控制DOM渲染会打断关闭动画流程 useDelayUnmount的状态逻辑与组件渲染不同步,且关闭按钮属性错误导致无法正常交互
修复步骤
1. 修正useDelayUnmount Hook逻辑
优化状态更新逻辑,避免不必要的重渲染,确保仅在isMounted变化时触发延迟:
function useDelayUnmount(isMounted: boolean, delayTime: number) { const [shouldRender, setShouldRender] = useState(isMounted); useEffect(() => { let timeoutId: NodeJS.Timeout; if (isMounted) { setShouldRender(true); } else { timeoutId = setTimeout(() => setShouldRender(false), delayTime); } return () => clearTimeout(timeoutId); }, [isMounted, delayTime]); return shouldRender; }
2. 调整模态框组件渲染逻辑
保证overlay和模态框在动画期间保持DOM存在,仅在动画完成后移除,同时修复关闭按钮的属性错误:
const Modal: React.FC<PropsWithChildren & IModal> = ({ children, isOpen, nodeId, onClose, className, }) => { const shouldRender = useDelayUnmount(isOpen, 300); // 与transition时长保持一致 if (!shouldRender) return null; return ReactDOM.createPortal( <> {/* overlay在渲染期间始终存在,通过isOpen控制透明度动画 */} <span onClick={onClose} className={`${classes.overlay} ${isOpen ? '' : classes.overlayHidden}`} /> <div className={`${classes.modal} ${isOpen ? classes.active : ''} ${className}`} > <div> <span onClick={onClose} className='text-2xl cursor-pointer' {/* 修正iconName为className */} >×</span> </div> {children} </div> </>, nodeId ? document.getElementById(nodeId)! : document.body ); };
3. 更新SCSS样式,补充完整过渡动画
确保overlay和模态框的过渡时长与useDelayUnmount的延迟时间严格匹配:
.overlay { @apply fixed top-0 left-0 bottom-0 right-0 w-full h-full bg-black opacity-30 backdrop-blur-sm; transition: opacity 0.3s ease; // 添加overlay过渡动画 } .overlayHidden { @apply opacity-0; // 关闭时逐步透明 } .modal { @apply fixed w-[600px] min-h-[250px] p-4 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-xl opacity-0 invisible transition-all duration-300; // 统一过渡时长 } .active { @apply opacity-100 visible; // 移除重复的translate,初始已设置居中 }
4. 首页组件保持原逻辑即可
核心原理
useDelayUnmount在isOpen变为false时,延迟一段时间再将shouldRender设为false,确保动画完整执行- overlay和模态框在
shouldRender为true时始终存在,通过isOpen切换样式类触发过渡动画 - 过渡时长与延迟时间严格对齐,保证动画结束后再从DOM中移除组件
内容的提问来源于stack exchange,提问作者Ali Ehyaie
相关产品推荐
相关产品推荐

