React Transition Group

February 16, 2020

You can view a video tutorial running through this above, and I've provided a Github repository with all code in the example

I was recently building a React application in which users could add or remove inline tags. I found it a bit jarring that clicking the add button caused a brand new tag to blast onto the screen immediately, and clicking to remove the tag caused the tag to immediately vanish in a fwoosh. As someone who spends much of his time thinking about great experiences, the jarring nature had me reaching for a softer, CSS animation solution.

Fading in elements is pretty easy using CSS 3 animations, so I implemented those first, but was immediately at a loss for how to elegantly handle the fade out for each component, which would require adding some set of “transition-out” css classes programatically as the element was removed. This would require yet another solution for the cradle to grave life of these tags to achieve the effect I wanted.

In comes React Transition Group, which seamlessly allowed me to implement transition effects for components as they entered and exited. It’s a technology I enjoyed using so much I thought I’d document my experience with it for others to build on and as a quick guide for myself.

My Test Application

I built a quick little test application to show the effect, which you can see in this Github Repository. The point was to show a very simple set of objects that transitioned in and out when you tap on them and I used three primary technologies.

I’ll mainly focus on the file [.code_snippet]TileGroup.js[.code_snippet] as this holds all the React Transition Group logic, but the above libraries were used to develop the end-to-end example you see.

The App

The App has a few components that make it up, but most relevant to understanding Transition Group is the nested components of [.code_snippet]App.js[.code_snippet] > [.code_snippet]TileGroup.js[.code_snippet] > [.code_snippet]Tile.js[.code_snippet]. I wired the application so that whenever the [.code_snippet]AddButton[.code_snippet] component is pressed, it updates the state of the application, which is then passed to TileGroup, which then creates a Tile for each object stored in the state.

For this reason, outside of the Styled Components to make it look pretty and the addItem and removeItem functions to manage state, the [.code_snippet]App.js[.code_snippet] is super simple.

The TileGroup

For the sake of example, the above snippet is what the TileGroup would look like without using any Transition Group magic. It’s simply a functional component which takes in the list of items as props, and then iterates over those items to create a unique Tile component for each item in the state. But _no_ transition in and transition out animation would be included, so every time a Tile was added or removed it would simply flash off the screen.

Below is what the finished product looks like using Transition Group. Note the [.code_snippet]TileGroup[.code_snippet] component has the exact same structure with the exception of adding in [.code_snippet]<TransitionGroup[.code_snippet] and [.code_snippet]<CSSTransition>[.code_snippet] which we will unpack below. I refactored this base code to include Transition Group.

Take notice of a few nuances

What does this look like? I used the [.code_snippet]classNames=transition[.code_snippet] and above in my styled component, I defined those css classes to look like the below snippet. Note each class begins with [.code_snippet]transition-[.code_snippet] because of the settings within the [.code_snippet]CSSTransition[.code_snippet] Component.

Now, because of [.code_snippet]TransitionGroup[.code_snippet] orchestrating the elements coming in and out, and [.code_snippet]CSSTransition[.code_snippet] applying classes to each individual Tile as it gets added, you will notice in your DOM via Dev Tools that [.code_snippet]transition-enter[.code_snippet] and [.code_snippet]transition-enter-active[.code_snippet] get applied over that 300 millisecond time window, and same with the [.code_snippet]-exit[.code_snippet] and [.code_snippet]-exit-active[.code_snippet] classes. _The orchestration between the component and these CSS classes is what achieves the desired effect_.

Conclusion

It takes a little getting used to, but once you understand the basics, I found it to be a delightful way to ensure my components got the animation treatment I desired. Again if you want to follow along more closely; take a look at the Github Repository or watch the video which goes a little more in depth on the solution.