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

如何为条件渲染组件添加动画?React Motion UI Pack侧边导航问题

解决React Motion UI Pack侧边导航滑出动画不生效的问题

你的问题根源在于条件渲染直接卸载了Transition组件,导致离开动画根本没有执行的机会。React Motion UI Pack的Transition组件需要在状态切换时保持挂载(至少直到离开动画完成),不能通过isThere直接决定是否渲染它。下面是具体的解决方案:

核心思路

把侧边导航的显示/隐藏逻辑从「条件渲染组件」改为「用Transition的in属性控制动画状态」,让Transition始终存在于DOM中,通过in的布尔值触发进入/离开动画,动画完成后再处理后续状态(比如隐藏遮罩)。

修改后的完整代码示例

constructor(props){
  super(props);
  // 初始状态根据窗口宽度自动判断是否打开侧边栏
  this.state = {
    isOpen: window.innerWidth > this.props.breakWidth,
    showOverlay: false
  };
  this.updatePredicate = this.updatePredicate.bind(this);
  this.handleToggleClick = this.handleToggleClick.bind(this);
  this.handleOverlayClick = this.handleOverlayClick.bind(this);
  this.handleLeaveComplete = this.handleLeaveComplete.bind(this);
}

componentDidMount() {
  this.updatePredicate();
  window.addEventListener("resize", this.updatePredicate);
}

componentWillUnmount() {
  window.removeEventListener("resize", this.updatePredicate);
}

updatePredicate() {
  const shouldOpen = window.innerWidth > this.props.breakWidth;
  this.setState({ 
    isOpen: shouldOpen,
    // 窗口宽度超过阈值时自动关闭遮罩
    showOverlay: shouldOpen ? false : this.state.showOverlay
  });
}

handleToggleClick(){
  // 点击按钮时打开侧边栏并显示遮罩
  this.setState({ isOpen: true, showOverlay: true });
}

handleOverlayClick(){
  // 点击遮罩仅触发关闭动画,遮罩在动画完成后再隐藏
  this.setState({ isOpen: false });
}

handleLeaveComplete(){
  // 离开动画完成后关闭遮罩
  this.setState({ showOverlay: false });
}

render() {
  const { attributes, classes, Tag, src, href, children } = this.props;
  const sidenav = (
    <Tag {...attributes} className={classes} key="sidenav">
      <ul className="custom-scrollbar">
        {src && (
          <li>
            <div className="logo-wrapper">
              <a href={href}>
                <img src={src} className="img-fluid"/>
              </a>
            </div>
          </li>
        )}
        {children}
      </ul>
    </Tag>
  );

  return (
    <div>
      {/* 始终渲染Transition,用in属性控制动画触发 */}
      <Transition
        component={false}
        appear={{ opacity: 0.2, translateX: -300 }}
        enter={{ opacity: 1, translateX: 0 }}
        leave={{ opacity: 0.2, translateX: -300 }}
        in={this.state.isOpen}
        onLeaveComplete={this.handleLeaveComplete}
      >
        {sidenav}
      </Transition>

      {/* 仅在窗口宽度小于阈值时显示切换按钮 */}
      {window.innerWidth <= this.props.breakWidth && (
        <Button color="primary" onClick={this.handleToggleClick} key="sideNavToggles">ClickMe</Button>
      )}

      {/* 遮罩仅在侧边栏打开且窗口宽度小于阈值时显示 */}
      {this.state.showOverlay && (
        <div id="sidenav-overlay" onClick={this.handleOverlayClick} key="overlay"></div>
      )}
    </div>
  );
}

关键修改点说明

  1. 状态拆分与逻辑优化

    • 用isOpen替代原来的isThere,专门控制侧边栏的显示/动画状态,初始值根据窗口宽度自动设置
    • 窗口大小变化时,自动同步isOpen状态,同时避免干扰用户手动打开的遮罩状态
  2. 始终渲染Transition组件

    • 不再用isThere做条件渲染,让Transition始终存在,通过in={this.state.isOpen}控制动画的触发
    • 当isOpen从true变为false时,Transition会自动执行leave定义的动画,而不是直接卸载组件
  3. 遮罩状态同步

    • 添加onLeaveComplete回调,在离开动画完全结束后再隐藏遮罩,避免遮罩提前消失导致的体验断层
    • 优化遮罩的显示条件,仅在窗口宽度小于阈值且侧边栏打开时显示(窗口宽度足够大时不需要遮罩)

这样修改后,点击遮罩时就能看到完整的滑出动画了,同时保留了窗口大小变化时的自动适配逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:51:03