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

Material UI Transition搭配Snackbar使用时onExited事件不触发问题

问题原因

这个问题在Material UI的Snackbar组件使用中非常常见,核心是两个错误用法导致的:

  • 你把slideTransition定义在父组件的渲染逻辑内部,每次父组件重渲染时这个函数组件的引用都会更新,React会把它判定为全新的组件,直接销毁旧实例、创建新实例,退出动画的生命周期直接被中断,onExited自然没有触发机会。
  • 你给Slide组件绑定回调的逻辑会覆盖Snackbar的内置回调:你先展开了Snackbar传递给Transition组件的props,再自定义onEntered和onExited,这会直接覆盖Snackbar内部依赖的过渡生命周期回调,导致Snackbar的退出流程逻辑异常。

修复方案

  1. 把slideTransition移到父组件外部定义,避免每次渲染生成新的组件引用,如果需要用到父组件内部的回调,可以通过props传递:
// 移到组件外部定义
const slideTransition = (props) => {
  // 先执行Snackbar内置回调,再执行自定义逻辑,避免打断内置流程
  const handleEntered = () => {
    props.onEntered?.();
    props.customOnTransition?.();
  };
  const handleExited = () => {
    props.onExited?.();
    props.customOnTransition?.();
  };
  return <Slide {...props} direction='right' onEntered={handleEntered} onExited={handleExited} />;
};

// 父组件内使用时传入自定义回调
return (
  <div>
    <Snackbar
      open={open}
      autoHideDuration={3000}
      onClose={handleClose}
      TransitionComponent={slideTransition}
      TransitionProps={{ customOnTransition: handleExited }}
    >
      <div>
        <AlertWrapper severity={snackbarVar()[0]?.severity}>
          {snackbarVar()[0]?.message}
        </AlertWrapper>
      </div>
    </Snackbar>
  </div>
);
  1. 如果不想把组件移到外部,也可以用useCallback包裹slideTransition的定义,保证引用稳定:
const slideTransition = useCallback((props) => {
  const handleEntered = () => {
    props.onEntered?.();
    handleExited();
  };
  const handleExitedCb = () => {
    props.onExited?.();
    handleExited();
  };
  return <Slide {...props} direction='right' onEntered={handleEntered} onExited={handleExitedCb} />;
}, [handleExited]);

另外需要注意不要在Snackbar过渡过程中直接卸载组件,要通过open属性控制组件的展示隐藏,等过渡完成后再做数据清理逻辑。


内容的提问来源于stack exchange,提问作者Peter Boomsma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:51:03