April 25, 2019

Tutorials

Animating React Route Transitions

With react Router we can create web applications with multiple pages and sections and we can change them dynamically.

Attention to detail is the key to make any UI design look professional, one of the most important things in user experience design is using the right animations and transitions when user interacts with our product.

CSS transitions generally run smoother than js animations so in this tutorial we’ll learn how to animate react router route transitions using css and react transition group.

final result

FULL PROJECT AVAILABLE HERE

1- install dependencies

after installing react, install the following dependencies(react router, react router dom and react transition-group) using npm install command:

npm install --save react-router react-router-dom react-transition-group@1.x 
  • this method works with react router v4 and above

2- setup routes

 Now open index.js and add BrowserRouter to your project:

import { BrowserRouter } from "react-router-dom";

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

then we setup our routes and links in App.js, we only have two links and two routes, route1 and route2

function App() {
  return (
    <div className='container'>
      <div className='links'>
        <Link to='/'>
          Route 1
        </Link>
        <Link to='/2'>
          Route 2
        </Link>
      </div>
    
      <div className='routes'>
        <Switch>
          <Route exact path='/' component={Route1} />
          <Route path='/2' component={Route2} />
        </Switch>
      </div>

    </div>
  );
}

// components
function Route1(){
  return (  
    <div className='route one'>
      <h2>this is route 1</h2>
    </div>
  );
}

function Route2(){
  return (  
    <div className='route two'>
      <h2>this is route 2</h2>
    </div>
  );
}
 
export default App;

3- Higher order component to animate route transition

Higher order components (aka HOC) receive components as arguments, add more functionalities to them and return a new componet, with HOCs  we can prevent repeating our selves.

So we’ll create a hoc to animate the component we pass to it on route transition. I name it Routetransit.js, it gets two arguments, the route component and css transition class name:

import { CSSTransitionGroup } from 'react-transition-group';

const Routetransit = (Page, transitionClass) =>{

  return props=>
      <CSSTransitionGroup 
        transitionAppear={true}
        transitionName={transitionClass}
        transitionAppearTimeout={500}
        transitionEnterTimeout={500}
        transitionLeaveTimeout={500}>
      
        <Page {...props}/>

      </CSSTransitionGroup > 
}

export default Routetransit;

CSSTransitionGroup has multiple properties, transitionAppear means the component will be animated the first time the component is loaded.and timeout properties control animation duration.

after creating Routetransit HOC, import it in App.js and use it as Rout’s component property and pass the component and animation css class name:

import Routetransit from './Routetransit';
.
.
.
<div className='routes'>
        <Switch>
          <Route exact path='/' 
component={Routetransit(Route1, 'fadeInDown')} />
          <Route path='/2' 
component={Routetransit(Route2, 'fadeInDown')} />
        </Switch>
</div>
.
.
.

4- add styling and animation classes

first we add some styles to our elements:

.container{
      display: flex;
      padding: 15px;
      font-family: sans-serif;
  }
  .links a{
    display: block;
    font-size: 18px;
    margin-top: 10px;
  }
  .routes{
      margin-left: 15%;
      width:50%;
  }
  .route{
      padding: 15px;
      height: 500px;
      color: white;
      text-align: center;
  }
  .one{
      background: tomato;
  }
  .two{
      background: slateblue;
  }

then we will add the classes needed for every phase of route transition, appear, enter and leave, note that transition class name and durations should be exactly equal to declared values in Routetransit.js.

You can create any kind of transition you want, I’ll create a fade in down animation by changing the element’s opacity and transform translateY:

.fadeInDown-enter {
    opacity: 0.01;
    transform: translateY(-30%);
  }
  
  .fadeInDown-enter.fadeInDown-enter-active {
    opacity: 1;
    transition: all 500ms ease;
    transform: translateY(0%);
  }
  
  .fadeInDown-leave {
    opacity: 1;
    transform: translateY(0%);
  }
  
  .fadeInDown-leave.fadeInDown-leave-active {
    opacity: 0.01;
    transition: all 500ms ease;
    transform: translateY(-30%);
  }

  .fadeInDown-appear {
    opacity: 0.01;
    transform: translateY(-30%);
  }
  
  .fadeInDown-appear.fadeInDown-appear-active {
    opacity: 1;
    transition: all 500ms ease;
    transform: translateY(0%);
  }

And now the route transition is animated as expected.