marnusw marnusw - 3 months ago 74
React JSX Question

Reactjs animate replace: How to wait for fade out before adding content to fade in?

I am trying to use

ReactCSSTransitionGroup
to replace content by fading out some content, waiting for it to disappear completely, and then fading in new content.

I am using
key
props which was the solution to this related question, so the content is being swapped out and animated. The problem, though, is that the new content is added to the DOM and takes up space in the flow from the start, rather that waiting until the old content has faded out. i.e., I can delay fading in with a transition delay, but the gap where the content will fade in is there from the start. Since CSS
visibility:hidden
still adds space for the element in the flow using that with
opacity
doesn't help either.

My question: Is there a way to achieve the desired outcome using only CSS? If not, I presume my component will have to detect the end of the fade-out transition and only then add the new element; what is the recommended React way for detecting and reacting to
transitionend
events?

My code thus far:

// jsx

let key = this.state.adding ? 'addForm' : 'addPlaceholder';

<ReactCSSTransitionGroup transitionName="fade">
<div key={key}>
{this.state.adding ? this.renderForm() : this.renderPlaceholder()}
</div>
</ReactCSSTransitionGroup>


// css

.fade-enter {
overflow: hidden;
opacity: 0.01;
}
.fade-enter.fade-enter-active {
opacity: 1;
transition: opacity .3s ease-in .3s;
}

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

Answer

It would seem there is no way to achieve the desired outcome using only CSS.

Since ReactCSSTransitionGroup intercepts the low-level API animation life-cycle methods there is no way detect the end of an animation when using it. The only remaining avenue is using the low-level API of ReactTransitionGroup directly.

By wrapping children in a component that informs the parent container when the life-cycle methods are called the parent can delay adding a new component to its children until it is informed that the transition of the leaving child has completed.

I have published the react-css-transition-replace component, which implements this, on GitHub/npm under the MIT license.