Christian Nwamba JS preacher. Developer 🥑. Building the web with the community @concatenateConf @forLoopAfrica. JS and Senior Advocacy for the Next Billion Users through Microsoft.

Animating Route Transitions with React Router

4 min read 1132

React Router v4 provides an intuitive, declarative API for building React apps that support navigation. However, there is not much in the docs, stack-overflow, or blogs that explain how to animate between routes when building UIs that require motion.

In this article, we’re going to create a React app with the new React Router (v4) and add some animations when navigating between views. At the end of the tutorial, you will see how to use Higher Order Components (HOC) to compose your components with the React’s CSSTransitionGroupplugin.

Here is a preview of the app we’ll be building:

Creating a New React Project

All the examples for this article are available in but in a real project, you will need to set a project with create-react-app at least. Let’s install this tool and setup a new project:

# Install globally
npm install -g create-react-app

#Create a new project
create-react-app router-animations

You need to install two more dependencies; react router, and the plugin for CSS transitions:

yarn add react-router-dom react-addons-css-transition-group

Notice that unlike the previous versions of React Router, we are installing react-router-dom and not react-router. v4 of React Router is platform independent which is why we’re installing react-router-dom which is dependent on react-router package itself and will pull it along in the installation process.

Just to have a less boring UI, copy the replace the index.css and logo.svg with the content found here and here respectively.

Create Page Routes

We’re all set to start adding routes. Create a pages folder in the src directory. This is where components that resolves to route pages will be added.

The simply has two pages:

  1. Subscribe page: Supposed email subscription page
  2. Thank you page: Thank you page shown after email subscription

Let’s start with the Subscribe page:

Next, add the Thank you page as well:

Apart from the obvious texts in the components, they have one thing in common — SubscribeForm. This is a UI component that just shows the subscription form.

Let’s create that as well:

The component renders a text input and a subscribe button if the thanks property is not defined. This property is defined on the SubscribeForm component only on the ThankYou page. If it is defined, the component just renders a button that says “Try Again”.

Depending on the page in view, the buttons are supposed to take us to the another page using the history.push() method when clicked.

Configure Routes and Browser Router

With the pages set to be rendered, let’s define their routes and what paths they should be rendered to. Update your App component with the following:

Here is what’s going on the component above:

  • Routes are configured using Route from the react-router-dom library which we imported.
  • Route is just a component and receives properties like path to specify what location the component will be mounted. It also receives component which is the component that should be mounted when the specified path is matched

Now to make the router actually work with React, we need to wrap the App component with the BrowserRouter component:

// ./src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

    <App />

The only change we made here is that we import the BrowserRouter and aliased it as Router (just for brevity), and then we wrap the App component with Router:

  <App />

You should have some navigation on screen when you open the app:

First Setup

The online code editor tailored for web applications

Higher Order Components

Higher Order Components (HOC) allows you to extend your React components. They are basically functions that takes a component and returns a component. As simple as that.

They become handy when you have two components sharing the same features leading to repeated logic. For example Subscribe page which is a component might have a logo and a white background. Same as the Thank You page. To add a logo and a white background to both components, we would need to write the feature in both component classes. Instead, what we can do is use a HOC that implements the shared feature, and call the HOC with the Subscribe or Thank You.

An example will make more sense. Create a component called PageShell in the components directory:

// ./src/components/PageShell.js

import React from 'react';
import logo from '../logo.svg';

const PageShell = Page => { 
  return props => {/* [1]*/}
    <div className="page">
        <img src={logo} alt="" />
        <Page {...props} /> {/* [2]*/}

export default PageShell;
  • The component is a function which is designed to receive a component (Page) as argument.
  • It wraps the received component with some fancy DOM content[1] and returns, passes in its props[2] and returns the component as a function.
  • The expectation is that PageShell will be used like this: PageShell(PageComponent)

Now let’s wrap the page components in App with PageShell:

The only difference is that before passing Subscribe and ThankYou to the component property, we first wrap it in PageShell leading to this new look:


The online code editor tailored for web applications

Transitioning in HOC

To achieve a transitions, each of the components needs to be wrapped with the ReactCSSTransitionGroup.

More great articles from LogRocket:

        <Page />

The transitionName maps to a CSS class that defines what happens at every phase of the animation. Here is a small and truncated snippet from index.css:

.SlideIn-appear {
  transform: translateX(30px);
  opacity: 0;
.SlideIn-appear.SlideIn-appear-active {
  opacity: 1;
  transform: translateX(0);;
  transition: all 0.6s linear;
.SlideIn-enter {
    opacity: 0;
    transform: translateX(30px);
.SlideIn-enter.SlideIn-enter-active {
    opacity: 1;
    transform: translateX(0);
    transition: all 0.2s linear 0.4s;
.SlideIn-leave {
    opacity: 1.0;
    transform: translateX(0);
.SlideIn-leave.SlideIn-leave-active {
    opacity: 0;
    position: absolute;
    width: 100%;
    transform: translateX(-30px);
    transition: all 0.2s linear;

ReactCSSTransitionGroup maps to each of these phases (appear, enter, and leave) and applies what ever transition effect is available on the CSS class definition. You can learn more in the React Docs on animation add-ons.

If we were building a large application, you will end up getting yourself messed up with repeated code when trying to wrap each of these components with ReactCSSTransitionGroup. With HOC, you can use ReactCSSTransitionGroup in the Page Shell once and wrap every components that needs the ReactCSSTransitionGroup with the page shell:

That’s all you need to get transitions up and going in your routes:


The online code editor tailored for web applications



LogRocket: Full visibility into your production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket combines session replay, product analytics, and error tracking – empowering software teams to create the ideal web and mobile product experience. What does that mean for you?

Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay problems as if they happened in your own browser to quickly understand what went wrong.

No more noisy alerting. Smart error tracking lets you triage and categorize issues, then learns from this. Get notified of impactful user issues, not false positives. Less alerts, way more useful signal.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Christian Nwamba JS preacher. Developer 🥑. Building the web with the community @concatenateConf @forLoopAfrica. JS and Senior Advocacy for the Next Billion Users through Microsoft.

Leave a Reply