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

react-transition-group中CSSTransition退出动画失效问题求助

解决CSSTransition退出动画失效及onExited钩子未触发问题

嘿,我帮你找出问题所在啦!你的CSSTransition退出动画失效、onExited(你代码里不小心写成onExied了,记得修正哦)钩子没触发,主要是classNames的配置逻辑没贴合组件的生命周期规则,加上退出阶段的样式衔接错误,导致过渡动画根本没触发。咱们一步步来修正:

一、先理清CSSTransition的类名生命周期逻辑

CSSTransition会在不同阶段给元素添加对应的类名,咱们需要让这些类名对应正确的样式状态,才能触发过渡:

  • 进入/首次挂载:appear → appear-active → appear-done/enter-done
  • 退出:exit → exit-active → exit-done(之后组件卸载,因为你开了unmountOnExit)

你的原始配置里,退出阶段的起始状态没衔接上进入完成后的激活状态,所以没有过渡的“起点”,自然不会有动画。

二、修正CSS样式

先把样式调整得更清晰,区分基础状态和激活状态:

/* 基础隐藏状态:默认在视口外 */
.getSecondLevelPanel {
  position: fixed;
  left: 450px;
  top: -100%;
  height: 100%;
  width: 400px;
  transition: all 250ms ease-out;
}

/* 激活显示状态:固定在顶部 */
.getSecondLevelPanel--opened {
  top: 0;
}

三、修正React组件的CSSTransition配置

重点调整classNames的映射,确保每个阶段的样式正确衔接,同时修正小细节:

import * as React from 'react';
import { CSSTransition } from 'react-transition-group';

export interface Props {
  isVisible: boolean; // 这里把Boolean改成boolean,TS里原始类型用小写
  children: React.ReactChild;
  onClose: () => void;
}

const SecondLevelPanel = (props: Props) => {
  return (
    <CSSTransition
      timeout={{ enter: 250, exit: 250 }} // 和CSS过渡时间保持一致,确保钩子触发时机正确
      in={props.isVisible}
      appear={true}
      enter={true}
      exit={true}
      classNames={{
        // 首次挂载/进入的起始状态:隐藏
        appear: 'getSecondLevelPanel',
        enter: 'getSecondLevelPanel',
        // 进入动画过程:切换到激活状态,触发过渡
        appearActive: 'getSecondLevelPanel getSecondLevelPanel--opened',
        enterActive: 'getSecondLevelPanel getSecondLevelPanel--opened',
        // 进入完成后保持激活状态
        enterDone: 'getSecondLevelPanel getSecondLevelPanel--opened',
        // 退出起始状态:保持激活状态(从top:0开始)
        exit: 'getSecondLevelPanel getSecondLevelPanel--opened',
        // 退出动画过程:切回隐藏状态,触发过渡
        exitActive: 'getSecondLevelPanel'
      }}
      unmountOnExit={true}
      onEntered={() => {
        alert('entered');
      }}
      onExited={() => { // 这里修正了拼写错误
        alert('exited');
      }}
    >
      {/* 给内容加个容器,避免样式冲突 */}
      <div className="second-level-panel-content">
        <a onClick={() => props.onClose()}>Close</a>
        {props.children}
      </div>
    </CSSTransition>
  );
};

export default SecondLevelPanel;

四、关键修正点说明

  1. classNames的正确衔接:
    • 退出阶段的exit类必须包含激活状态(getSecondLevelPanel--opened),这样动画才会从top:0的状态开始过渡到top:-100%。
    • exitActive类切换回基础隐藏状态,触发CSS过渡动画。
  2. timeout与CSS过渡时间匹配:把exit的timeout改成250ms,和CSS里的过渡时长一致,确保动画完全结束后才触发onExited钩子并卸载组件。
  3. TS类型修正:把Props里的Boolean改成boolean,符合TypeScript的类型规范。
  4. 拼写修正:把onExied改成正确的onExited,不然钩子肯定不会触发😅。

现在你再测试一下,点击Close按钮后,面板会平滑地滑出视口,动画结束后onExited的alert会弹出,组件也会正常卸载啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:02:12