React animate transition between components

Rick Jolly picture Rick Jolly · Oct 30, 2015 · Viewed 23.4k times · Source

I'd like to animate between two components where the first component fades out and is removed from the DOM before the next component is added to the DOM and fades in. Otherwise, the new component is added to the DOM and takes up space before the old component is removed. You can see the problem in this fiddle:

http://jsfiddle.net/phepyezx/4

// css snippet
.switch-enter {
    opacity: 0.01;
}
.switch-enter.switch-enter-active {
    opacity: 1.0;
}
.switch-leave {
    opacity: 1.0;
}
.switch-leave.switch-leave-active {
    opacity: 0;
}

// React snippet 
<ReactCSSTransitionGroup transitionName="switch">
    <div key={key} className={className}>{this.text()}</div>
</ReactCSSTransitionGroup>

An unacceptable solution (for me) is to hide the original component with css before transitioning to the new component as seen here:

http://jsfiddle.net/phepyezx/5

// Change to css
.switch-leave {
    visibility: hidden;
    height: 0px;
    width: 0px;
    opacity: 1.0;
}

Is there a way to "delay" react from mounting a new component before the original is removed? I'm open to velocity or some other library to achieve this.

Thanks

Answer

Jonny Buchanan picture Jonny Buchanan · Oct 30, 2015

Another solution is to make the incoming and outgoing elements take up the same space, for example by having them both absolutely positioned:

<ReactCSSTransitionGroup
    className="container"
    component="div"
    transitionName="switch">
...

.container {
    position: relative;
}
.container > div {
    position: absolute;
}

http://jsfiddle.net/phepyezx/7/


You can use transition-delay to wait until the leaving component disappears before making the entering component appear, e.g.:

.fade-enter {
  opacity: 0.01;
}
.fade-enter.fade-enter-active {
  opacity: 1;
  transition: opacity 1s;
  transition-delay: 1s;
}

.fade-leave {
  opacity: 1;
}
.fade-leave.fade-leave-active {
  opacity: 0.01;
  transition: opacity 1s;
}