How to use React Transition Group & React Animation Library
A few months ago, I gave a talk with a coworker at the tech conference Connect.Tech about the ever-growing need for responsive web design when building websites and applications. During the presentation, we discussed a few different ways to approach it, specifically when it comes to the JavaScript framework React.
While I won’t go into all the details in our talk of how to approach responsive design (if you’d like, you can see the full slide deck of the talk here), I did want to share a handy React animation library I stumbled across while building the mobile-responsive demo application, called React Transition Group.
React Transition Group
What makes it different?
Unlike other React animation libraries like React Spring or React Reveal, React Transition Group “exposes simple components useful for defining entering and exiting transitions…it does not animate styles by itself. Instead it exposes transition stages, manages classes and group elements and manipulates the DOM in useful ways, making the implementation of actual visual transitions much easier.”
React Transition Group is a lower-level type of animation library. It doesn’t care nearly as much about what type of animation you’d like to do, it just makes it easier to do any sort of animation on any React component with as little hassle as it can.
And it doesn’t hurt to know that React Transition Group began in the original React framework (it’s mentioned in the docs) before being spun out into a new package to be maintained by the community. That’s a pretty good endorsement for trying RTG, in my book.
Now that you know a little more about RTG’s approach to animation, let me cover a few of the different component options it gives users, and how they work.
Types of RTG Components
React Transition Group offers four different types of components for users to choose from based on their animation needs.
Transition
The first component to cover is Transition
. This component lets you describe a transition from one component state to another over a span of time with a simple API. Most commonly it’s used to animate the mounting and unmounting of a component, but it can also be used to describe in-place transition states as well. Personally, I tend to favor CSSTransition
over the straight Transition
component, but that’s just me.
The transition component tracks the “enter” and “exit” states for the component. The four main states a Transition
can be in are:
'entering'
'entered'
'exiting'
'exited'
The transition state is toggled on via the in
prop, when it’s true
the component will begin the entering
stage for the duration of the transition until it’s fully visible, at which point it will switch to the entered stage
. Upon exit, the same things will happen with exiting
and exited
.
A simple example of fading in a component on enter and fading it out on exit might look something like this:
This illustrates using React Transition Group’s Transition component to fade a component into view for the user.
In the example above, once the inProp
prop is true
, the Transition
component will activate and begin fading in to view courtesy of the transitionStyles
variable (where opacity is defined) that correspond to the various “enter” or “exit” stages I outlined earlier.
It’s worth noting this is a platform-agnostic base component — if you’re looking for CSS transitions (like I was for my use case), you’ll probably want the CSSTransition
component instead.
CSSTransition
If you’re using CSS transitions or animations, the CSSTransition
component is what you’ll want to use; it’s built upon the Transition
component, so it inherits all of its props.
To work, CSSTransition
applies a pair of class names during the appear
, enter
, and exit
states of the transition. The first class is applied and then a second *-active
class in order to activate the CSS transition. After the transition, matching *-done
class names are applied to persist the transition state.
For instance, if your CSSTransition
component’s classNames
property is sample
, you’d first see sample-enter
, then sample-enter-active
, and finally sample-enter-done
for the ending state when the animation is done. And when it’s time to reverse the animation (such as with a modal or slider that needs to disappear or exit the screen), you’d see it cycle through sample-exit and sample-exit-active
and sample-exit-done
on your component’s classNames
property.
Here’s a simplified code sample of what the JSX and accompanying CSS classes might looks like for making a div
of text fade in or out. (I’ve omitted the imports at the top of the file because they’re the same named import for each type of component from RTG: import { CSSTransition } from 'react-transition-group';
.)
First the JavaScript code showing the CSSTransition
component wrapping a div
element to show or hide based on the state of isVisible
, which is toggled by the button
element underneath.
Here’s the JavaScript JSX code where the CSSTransition component is used to wrap the div and text to show or hide.
And here’s the CSS classes that the CSSTransition
component would experience once isVisible
became true
and triggered the in
prop to fade the text in or out (just like with the original Transition
component).
The CSS transition states that will actually cause the text wrapped in the CSSTransition to component to fade in and out of view.
*-active
classes represent which styles you want to animate to, so it’s important to add the transition
declaration only to them, otherwise transitions might not behave as intended. This might not be obvious when the transitions are symmetrical, i.e. when *-enter-active
is the same as *-exit
, but it becomes apparent quickly in more complex transitions.
Let’s move on now to React Transition Group’s next option: SwitchTransition
.
SwitchTransition
This component is useful if you want to control the render between state transitions, it’s inspired by Vue transition modes. Based on the selected mode (in-out
or out-in
), and the child’s key which is the Transition
or CSSTransition
component, the SwitchTransition
makes a consistent transition between them.
If out-in
mode is selected, SwitchTransition
waits until the old child leaves and then inserts a new child. If the in-out
mode is selected, the SwitchTransition
inserts a new child first, waits for the new child to enter and then removes the old child.
Here’s an example so you can see how the code might be structured to make two different buttons “switch” places in the DOM based on the current state. Once again, imports at the top of the file omitted for brevity.
The Button element gets replaced each time it’s clicked with a new button featuring the opposite text of what the previous button text was, courtesy of SwitchTransition.
Here, SwitchTransition
wraps the CSSTransition
component, which actually handles the logic and animating of entering a new Button
and exiting the existing one. The key
in CSSTransition
keeps track of state in the component, and every time the state changes (based on a button click), the CSSTransition
component takes action and SwitchTransition
handles the keeping the old button visible until after the new button has appeared, which CSSTransition
is fading out based on its event listener.
That addEndListener
function is crucial to animating the switch between elements, without it, the state (and components) will instantaneously flip like there’s no animations at all.
Here’s the CSS for the fade
class name associated with CSSTransition
.
This CSS is really for the animated entrances and exits of the buttons in the DOM, but I wanted to show it anyway.
The CSS here is really concerned with the CSSTransition
component wrapped inside of SwitchTransition
, but I figure the more sample code you see for how to animate things in and out of the DOM, the better.
It takes some trial and error to get it right, but the documentation for SwitchTransition
is good and I’m sure you’ll figure it out without much of a problem if this is the kind of animation you desire in your application.
TransitionGroup
Last but not least is the <TransitionGroup>
component. This component manages a set of transition components (<Transition>
and <CSSTransition>
) in a list. Like with the individual transition components, <TransitionGroup>
is a state machine for managing the mounting and unmounting of components over time.
Please note that <TransitionGroup>
does not define any animation behavior. Exactly how a list item animates is up to the individual transition component, which means you can mix and match animations across different list items, which could be handy.
Unlike SwitchTransition
which lets you control the entering and exiting of elements in the DOM, TransitionGroup
will make the animations happen simultaneously (i.e., to remove the old child and insert a new child at the same time).
Take a look at this example of a simple chore list that can have chores removed from it once they’re completed. First, the JSX code with no imports in the example.
TransitionGroup wraps the list of CSSTransition components which will be removed from the list as they’re completed.
And, here’s the CSS that will make the chores fade out of the DOM as they’re removed.
Once more, the CSS belongs to the CSSTransition components so they can enter and leave the DOM in an animated fashion.
And with that, I’ve covered all the main component options React Transition Group offers. All in all, using one or more of these components together gives you fine grained control over what type of and how your React components animate in the DOM. Now, let’s get down to the business of how exactly I used React Transition Group to animate my mobile navbar in my demo site.
How I used RTG in My React App
The use case I had for React Transition Group is a fairly standard one, I’m sure. For my app, a movie demo site I built using the Movie Database API for a data source, when it was in mobile view, I wanted the navbar (normally across the top of the page in larger layouts) to condense down to the well-recognized hamburger menu, and require users to click it to open the list of links.
What I needed was to animate a mobile-sized navbar to slide into and out of the DOM for the user, at the touch of a button. Seemed like a simple enough request.
Here’s a video of what I envisioned happening.
Easy enough, right? Slide a navbar in when the user clicks the hamburger icon. slide it back out when they click the icon again.
The code I’ll be showing you are actual snippets taken from the demo site you’re seeing in the video above. If you’d like to see the whole codebase for this project, it’s available on GitHub, and if you’d like to see a live version of the site, it’s available on this website (just make your desktop browser mobile-sized to see the animated navbar).
Step 1: Add CSSTransition Group to the Sidebar.js Component
The first thing I had to do after installing React Transition Group into my project’s dependencies with npm -i react-transition-group
, was add it to the component I wanted to animate.
This component is named Sidebar
and its full JavaScript code looks like this.
Sidebar.js
This is the entire Sidebar component. The code before the CSSTransition component is just the hamburger icon and click function to toggle CSSTransition into action.
I’ll quickly break down what goes into this component. The way that Sidebar
triggers the in
prop in the CSSTransition
component (which will reveal all the navigation links to other pages in the site housed within the sidebar) is with the toggleLinks
function.
Once toggleLinks
changes the expandedLinks
state to true
, the CSSTransition
component runs and adds the class name modifiers ( enter
, enter-active
, exit
, etc.) to the visible
class present on the CSSTransition
component.
And all I had to do to hide the sidebar links until I’m ready for them, was wrap the main div
surrounding all the links with the CSSTransition
component. Pretty straightforward, so far, right?
Step 2: Generate the CSS to Support RTG’s Animation Class Names
Now for the CSS. It’s long, I’ll admit — I did a lot of styling to make this navbar look just how I wanted, but try to bear with me. It’s really not complicated, just verbose from styling (and this is a condensed version where I cut out some extraneous CSS not relevant to this article).
Sidebar.scss
Yes, it’s a lot of CSS, but the finished product is worth it in my mind.
If you wade through all this styling and focus on the transform
and translate
properties in each class I’ve defined above, you’ll see what is causing the animation I want. I slide the navbar in to view on .visible-enter-active
with transition: transform 0.3s linear;
and slide it back out of view with .visible-exit-active
and transition: transform 0.3s linear;
. Piece of cake!
Conclusion
Responsive web design is only gaining more importance as technology touches more and more of our daily lives, and smooth animations to make that technology feel more natural are essential.
React Transition Group makes animations of all kinds easy by providing 4 basic components and an easy-to-use API unconcerned with the specific types of animation it’s enabling. This low-level implementation gives developers fine-grain control over exactly how their app’s components flow in the DOM for the best user experience they can provide. RTG is really easy to get up and running, and a pleasure to develop with.
Check back in a few weeks — I’ll be writing more about JavaScript, React, ES6, or something else related to web development.
Thanks for reading. If you’re looking to add some slick animations to your React app, I hope you’ll consider React Transition Group among the myriad of libraries out there. It makes animations simple and straightforward, even down to the tiny, micro-animation details. Give it a shot — you won’t regret it.
Read the original article or more interesting posts on Paige’s blog.
If you enjoyed reading this, you may also enjoy some of my other free pieces:
- “4 Solutions To Run Multiple Node.js or NPM Commands Simultaneously”
- “NVM, the Easiest Way to Switch Node.js Environments on Your Machine in a Flash”
- “The Absolute Easiest Way to Debug Node.js — with VS Code”
References and Further Resources
-
GitHub repo, React app with using React Transition Group
-
Live demo site of responsive app
-
Responsive design featuring React.js presentation deck
-
React Transition Group, site documentation