React meets GSAP

How to structure mounting and unmounting animations for your React Components

While developing my own React app I came to the point where I wanted to implement UI animations. I’ve tried things like ReactCSSTransitionGroup, react-motion, velocity and finally GSAP.


I’m not an animation expert but I think the API of GSAP is very easy to learn yet really powerful. I’ve spent just like an hour to understand how the basics of the framework work. react-motion did feel fine when it comes to pure state transitions, but there were situations where I had to do a bit more than just that. Also performance of GSAP is just wonderful, but I do not want to convince you of any framework. In this article I am going to show you how I’ve implemented GSAP into React. Generally I’m not a fan of CSS animations as I find them very hard to manage, also you can’t do things like pausing them.

Example first

Although this article is not about the animation itself, it might help you to see a working example for the code below. So here it is:

Keep all animations in one file

I didn’t want to flood my React components with all the animation stuff, so I always keep all my GSAP code in one file. That file is simply called “animation.js” and lives in the same folder where my component lives.

My React component file structure

One component exists of:

  • the container that handles server communication and everything that has nothing to do with the pure presentation
  • the view which is mostly markup and css, passing event callbacks to the container
  • the animation.js where you import everything you need from GSAP and then export all animations in just one big Javascript object

Please note: You will need the “onComplete” callback for everything to work. Don’t forget it. I will explain that later.

I will then load the animation.js into my container component and run the transitions from there.

Please note: The use of ReactDOM.findDOMNode is an anti pattern, use refs instead.

I am saving the DOM node of my component under this.dom.root, because this node must be passed to GSAP.

Running the transitions

I think the most obvious way to run transitions is to simply put them inside componentDidMount() and componentWillUnmount() live cycle methods. But that’s wrong, they are not meant to be used like that. While you can run animations inside of componentDidMount() you can’t do that in componentWillUnmount() because the component doesn’t wait for your animation to be finished.

TransitionGroup to the rescue

The react addon “TransitionGroup” covered this problem. TransitionGroup instead adds some more live cycle methods like componentWillEnter() and componentWillLeave().

Please note: The callback passed to the animation transition is the one we are calling in our onComplete animation callback. It is used to tell the TransitionGroup that we are done animating.

Initializing the TransitionGroup

You must wrap the component that contains the animation with this TransitionGroup and will then have access to the new live cycle methods. In my example I added the animations to a single Todo item, so my TodoList component includes the TransitionGroup to wrap the todo items.

That’s it!