Animating React Router v4 with ReactCSSTransitionGroup

Antonio Erdeljac
3 min readOct 27, 2017

There are many articles related to this topic, but I spent stupidly long time figuring out how to implement animations on route change using React Router v4 & ReactCSSTransitionGroup. That is why I decided to create this article and cover many errors that I have encountered. This is what we will achieve:

First Step - Create parent route

Let’s start by creating the parent route, or the ‘/’ route which will call main component on which we will render child components.

in index.js create:

import React from 'react';
import ReactDOM from 'react-dom';
import App from "./components/App";
import {BrowserRouter} from "react-router-dom";


ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);

Great, we are using BrowserRouter as our router, and App as our parent component (or the ‘/’ route).

Second Step - Create the App component

You can use your project structure, but in this article im going to put components into /components, and keep index.js outside.

Like this:

./MyProject
index.js
./components
App.js

Now let’s create the App.js component:

import React from "react";
import {Switch, Route} from "react-router-dom";
import Login from "./Login";
import Register from "./Register";
class App extends React.Component{
render(){
return (
<div>
<Switch>
<Route path="/login" component={Login}/>
<Route path="/register" component={Register}/>
</Switch>
</div>
)
}
}
export default App;

Great. Now we can start creating the child routes.

Third Step - Create Child Components

Let’s start by creating Login.js component inside our /components folder

import React, { Component } from 'react';
import {Link} from "react-router-dom";
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

class Login extends Component {
constructor(props){
super(props);

this.state = {
isVisible: true
}

this.closeComponent = ev => {
ev.preventDefault();

this.setState({
isVisible: false
});

setTimeout(() => {
this.props.history.push('/')
}, 600)
}
}
render(){
return (
<ReactCSSTransitionGroup
transitionAppear={true}
transitionAppearTimeout={600}
transitionEnterTimeout={600}
transitionLeaveTimeout={200}
transitionName={this.props.match.params === '/login' ? 'loadComponent' : 'leaveComponent'}
>
{this.state.isVisible ?
<div className="container-fluid">
<div className="row">
<div className="col-2">
<div className="card">
<div className="card-body">
Login
<br/>
<button onClick={this.closeComponent}>
Close me
</button>
</div>
</div>
</div>
</div>
</div>
:
null}

</ReactCSSTransitionGroup>
)
}
}

export default Login;

This is a basic component setup, but there are some things that you might be unfamiliar with. I am setting state’s property isVisible: true so ReactCSSTransitionGroup will know when to animate the component leave, and when to animate enter / appearance. When close me button is clicked, ReactCSSTransitionGroup is going to animate leave animation. I am also checking in transitionName if current route is ‘/login’ and i select enter class so the ReactCSSTransitionGroup knows what animation to load if the router is active and what to load if its not.

You can use this example to create Register.js component.

Step Four - Creating the animation CSS

Anywhere in your project structure add a .css file which you will link in your index.html file

.loadComponent-appear {
opacity: 0;
}
.loadComponent-appear.loadComponent-appear-active {
opacity: 1;
transition: all 0.6s linear;
}
.loadComponent-enter {
opacity: 0;
}
.loadComponent-enter.loadComponent-enter-active {
opacity: 1;
transition: all 0.6s linear 0.4s;
}
.loadComponent-leave {
opacity: 1.0;
position:absolute
}
.loadComponent-leave.loadComponent-leave-active {
opacity: 0;
transition: all 0.6s linear;
position:absolute;
}



.leaveComponent-appear {
opacity: 0;
}

.leaveComponent-appear.leaveComponent-appear-active {
opacity: 1;
transition: all 0.6s linear;
}
.leaveComponent-enter {
opacity: 0;
}
.leaveComponent-enter.leaveComponent-enter-active {
opacity: 1;
transition: all 0.2s linear 0.4s;
}
.leaveComponent-leave {
opacity: 1.0;
position:absolute
}
.leaveComponent-leave.leaveComponent-leave-active {
opacity: 0;
transition: all 0.2s linear;
position:absolute
}

Note! the only changeable part of these classes’ names is leaveComponent & loadComponent. Other extensions like -enter -leave-active -enter-active are required for ReactCSSTransitionGroup to work.

That is it! Thank you for going through this article!

It would be great if you could correct my mistakes if you find any. Thank you!

--

--