07/09/2018, 17:00

[Advanced React] Animations with react-addons-transition-group

Why we have to use ReactTransitionGroup Definetely one thing that we can do animations in pure CSS. But when your application is going to reach a certain level of complexity, it's a challenge when you want to maintain your code. ReactTransitionGroup is the API upon which ReactCSSTransitionGroup ...

Why we have to use ReactTransitionGroup

Definetely one thing that we can do animations in pure CSS. But when your application is going to reach a certain level of complexity, it's a challenge when you want to maintain your code.

ReactTransitionGroup is the API upon which ReactCSSTransitionGroup is built. The main difference between the two is that ReactTransitionGroup animations are written in Javascript instead of CSS, and a callback is provided to be invoked when animations are complete instead of relying on CSS transition events.

Warm up

Let’s start with a page that has a div that’s conditionally shown based on the flag shouldShowBox, we’ll leave transition groups out for now. P/s: I made React app with create-react-app, you can install it before we start

npm install -g create-react-app
create-react-app react-transition-example

We add a component Page with a button, then we call it in App.js

Page.js

import React from 'react';

class Page extends React.Component {
  state = {
    shouldShowBox: true
  };

  toggleBox = () => {
    this.setState({
      shouldShowBox: !this.state.shouldShowBox
    });
  };

  render () {
    return <div className="page">

      { this.state.shouldShowBox && <div className="box"/>}

      <button
        className="toggle-btn"
        onClick={this.toggleBox}
      >
        toggle
      </button>
    </div>;
  }
}

export default Page

When shouldShowBox is true, the “.box” is visible, and when it’s false, it’s not.

Adding the React Transition Group

npm install react-addons-transition-group

Then we import into our Page.js

import TransitionGroup from 'react-addons-transition-group';

And now our component becomes:

// ...
  render () {
    return <div className="page">

      <TransitionGroup>
        { this.state.shouldShowBox && <div className="box"/>} 
      </TransitionGroup>

      <button
        className="toggle-btn"
        onClick={this.toggleBox}
      >
        toggle
      </button>
    </div>;
  }
// ...

To give components inside the TransitionGroup the flexibility of having differing animations, the TransitionGroup does not define animations itself, but will call the corresponding enter or leave animation hooks on its child components when the child components are added or removed.

You will typically only need these two lifecycle hooks -

componentWillEnter(callback)

Called on components that are added to an existing TransitionGroup, at the same time as the component’s componentDidMount. Not called on the initial render of the entire TransitionGroup (e.g. when a page is initially loaded), for that you’d want componentWillAppear

componentWillLeave(callback)

Called on components that have been removed from a TransitionGroup. This is called before componentWillUnmount, and componentWillUnmount will not trigger until the callback here is called.

Note that you must call the supplied callbacks after your animation ends, otherwise your component will enter but not leave, or leave but not enter. Because ReactTransitionGroup relies on those hooks to exist, and a div doesn’t have those hooks defined, we’ll have to first move our <div className=”box”/>into its own component. Then add in the animation lifecycle hooks. We’ll be using GSAP’s TweenMax for animation, our code will be: Box.js

import React from 'react';

export default class Box extends React.Component {
    componentWillEnter(callback) {
        const el = this.container;
        TweenMax.fromTo(el, 0.3, { y: 100, opacity: 0 }, { y: 0, opacity: 1, onComplete: callback });
    }

    componentWillLeave(callback) {
        const el = this.container;
        TweenMax.fromTo(el, 0.3, { y: 0, opacity: 1 }, { y: -100, opacity: 0, onComplete: callback });
    }

    render() {
        return <div className="box" ref={c => this.container = c} />;
    }
}

Change this line from our Page.js :

{this.state.shouldShowBox && <Box/>}

Dont forget to install gsap and styles.css

npm install --save gsap
.page {
  height: 100%;
}

.box {
  awidth: 100px;
  height: 100px;
  background-color: #3498DB;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

.toggle-btn {
  margin-top: 20px;  
  awidth: 80px;
}

Now we have a simple animation using ReactTransitionGroup ! Demo

0