Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate conditionally-rendered components?

I'm trying to use React Motion UI Pack to animate the slide-in/slide-out animation for my Side Navigation. This is it:

constructor(props){
  super(props);
  this.state = {
    isThere: false,
    showOverlay: false
  } 
  this.updatePredicate = this.updatePredicate.bind(this);
  this.handleToggleClick = this.handleToggleClick.bind(this);
  this.handleOverlayClick = this.handleOverlayClick.bind(this);
}

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

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

updatePredicate() {
  this.setState({ isThere: window.innerWidth > this.props.breakWidth })
}

handleToggleClick(){
  this.setState({
    isThere: true,
    showOverlay: true
  })
}

handleOverlayClick(){
  this.setState({
    isThere: false,
    showOverlay: false
  });
}

let 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>
    { isThere ? (
      <Transition
      component={false}
      appear={{ opacity: 0.2, translateX: -300 }}
      enter={{ opacity: 1, translateX: 0 }}
      leave={{ opacity: 0.2, translateX: -300 }}
    >
        { sidenav }
      </Transition>
      ) : (
        <Button color="primary" onClick={this.handleToggleClick} key="sideNavToggles">ClickMe</Button>
      ) }
    {showOverlay && (
      <div id="sidenav-overlay" onClick={this.handleOverlayClick} key="overlay"></div>
    )}
  </div>
    );
  }
}

The utility seems awesome, yet there is something I cannot wrap my head around. My component renders button or the sidenav depending on the breakWith prop. Clicking on the rendered button causes the SideNav to slide-in anyway, this time together with an overlay. Transition allowed for a smooth slide-in animation, but now I would like to apply a slide-out one upon clicking on the overlay.

Few hours passed and I'm starting to think it is impossible. Rendering of components is conditional & state-based (the isThere ? (... part in render()), right? As the pack offers no willLeave props, there seems to be no time to animate the leave in between the change of state and the re-render with the conditionally-rendered element already missing.

Or am I missing something?

like image 980
Jakub Strebeyko Avatar asked Feb 11 '26 19:02

Jakub Strebeyko


1 Answers

yes - the answer found here effectively addresses the problem. To solve it, I moved the conditional logic of the component up, created appropriate variable, and encapsulated it inside a <Transition> in render(). If there is a lesson to be learned here, it is that <Transition> from Reakt Motion UI Pack (and, perhaps, elsewhere) does not fire its leave animation if surrounded by a conditional statement, making it impossible to use it together with ternary operator if you don't want the false component to be animated as well.

like image 119
Jakub Strebeyko Avatar answered Feb 13 '26 08:02

Jakub Strebeyko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!