React MUI Modal组件关闭时exit退出动画不生效如何解决?
问题原因
退出动画不生效的核心原因有两点:
- MUI的
Modal组件在open属性设为false时会直接从DOM树中卸载整个组件节点,你的退出动画需要1秒执行时长,但组件还没等动画触发就已经被移除,自然无法看到动画效果。 - 你当前的className绑定逻辑存在缺陷:当
open为false时Modal已经停止渲染,no-animation类根本没有机会挂载到DOM节点上,动画无法触发。
修复方案
提供两种可落地的修复方案,你可以根据需求选择:
方案1:使用MUI内置过渡组件(推荐)
MUI的Modal原生支持过渡效果配置,不需要自定义CSS动画,适配性更高:
- 首先导入Slide过渡组件:
import { Slide } from '@mui/material';
- 定义过渡组件,修改Modal配置:
// 定义滑入方向为从左进入 const Transition = React.forwardRef(function Transition(props, ref) { return <Slide direction="left" ref={ref} {...props} />; }); const Menu: FC = () => { const [open, setOpen] = useState(false); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); return ( // 省略其他不变的代码 <Modal open={open} onClose={handleClose} TransitionComponent={Transition} keepMounted // 保证关闭动画执行过程中节点不被卸载 > // 省略Modal内部代码 ) }
该方案不需要保留你之前写的animation、no-animation相关CSS代码。
方案2:保留自定义CSS动画
如果要继续使用你写的keyframes动画,只需要调整状态逻辑,等动画执行完再卸载Modal:
- 新增关闭状态控制,修改关闭逻辑:
const Menu: FC = () => { const [open, setOpen] = useState(false); // 新增关闭状态标记 const [isClosing, setIsClosing] = useState(false); const handleOpen = () => setOpen(true); const handleClose = () => { // 先触发退出动画 setIsClosing(true); // 等待1秒动画执行完成后,再卸载Modal setTimeout(() => { setOpen(false); setIsClosing(false); }, 1000) }; return ( // 省略其他不变的代码 <Modal open={open} onClose={handleClose} className={isClosing ? "no-animation" : "animation"} keepMounted > // 省略Modal内部代码 ) }
- 优化CSS动画配置,避免动画结束后回弹:
.animation { animation-name: entrance; animation-duration: 1s; animation-fill-mode: forwards; /* 保持动画最后一帧状态 */ } .no-animation { animation-name: exit; animation-duration: 1s; animation-fill-mode: forwards; /* 保持动画最后一帧状态 */ }
内容的提问来源于stack exchange,提问作者Marco Ávila
相关产品推荐
相关产品推荐

