How to add reactjs animation library and Animate .css to animate

20.1k views Asked by At

I have this simple Todo List,

I need to add animate.css library animations when adding and removing. I'm really new to react. I have read the documentation, but it's really hard to understand,

This is a question asking for help with coding.

http://jsfiddle.net/johnthethird/NXCyC/7/

/** @jsx React.DOM */
var TodoList = React.createClass({
  propTypes: {items: React.PropTypes.array},
  render: function() {
    var createItem = function(itemText) {
      return <li>{itemText}</li>;
    };
    return <ul>{this.props.items.map(createItem)}</ul>;
  }
});
var TodoApp = React.createClass({
  getInitialState: function() {
    return {items: [], text: ''};
  },
  onChange: function(e) {
    this.setState({text: e.target.value});
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var nextItems = this.state.items.concat([this.state.text]);
    var nextText = '';
    this.setState({items: nextItems, text: nextText});
  },
  render: function() {
    return (
      <div>
        <h3>TODO</h3>
        <TodoList items={this.state.items} />
        <form onSubmit={this.handleSubmit}>
          <input onChange={this.onChange} value={this.state.text} />
          <button>{'Add #' + (this.state.items.length + 1)}</button>
        </form>
      </div>
    );
  }
});
React.renderComponent(<TodoApp />, document.body);
5

There are 5 answers

3
Sebastien Lorber On

See https://facebook.github.io/react/docs/animation.html

You can use ReactTransitionGroup and use the callbacks to setup the animate.css classes on the child nodes.

Note that you can't use directly ReactCSSTransitionGroup because of the class name convention it has: you have to control the animation class names in order to follow React convention. I mean .transitionName-enter-active is what ReactCSSTransitionGroup puts on the node to animate, while you would need something like .animate zoomIn.

Edit

According to this commit / issue I see you can now customize all of the ReactCSSTransitionGroup classnames.

Look at the proptypes:

  propTypes: {
    transitionName: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.shape({
        enter: React.PropTypes.string,
        leave: React.PropTypes.string
      }),
      React.PropTypes.shape({
        enter: React.PropTypes.string,
        enterActive: React.PropTypes.string,
        leave: React.PropTypes.string,
        leaveActive: React.PropTypes.string
      })
    ]).isRequired,
    transitionAppear: React.PropTypes.bool,
    transitionEnter: React.PropTypes.bool,
    transitionLeave: React.PropTypes.bool
  },

I think it is available only for React 0.14.0 (still in beta)

Unfurtunatly according to my tests, this is not enough to support easily Animate.CSS out of the box.

With the new version, one should be able to write:

var TodoList = React.createClass({
  getInitialState: function() {
      var todos = [  {text: "Init Todo1"}  ,  {text: "Init Todo2"}   ];
      return {todos: todos}; 
  },

  add: function() {
      var todos = this.state.todos;
      todos.push({text: "New!"});
      this.setState({todos: todos});
  },
  remove: function() {
      var todos = this.state.todos;
      todos.pop();
      this.setState({todos: todos});
  },

  render: function() {
    var todos = this.state.todos.map(function(todo, index) {
      return <Todo key={index} todo={todo}/>
    });
    return (
        <div>
            <div onClick={this.add}>Add</div>
            <div onClick={this.remove}>Remove</div>
            <br/>
            <div>
                <ReactCSSTransitionGroup transitionName={{enter: "animated bounce", enterActive: "animated bounce", leave: "animated tada",leaveActive: "animated tada"}}>
                    {todos}
                </ReactCSSTransitionGroup>
            </div>
        </div>
    );
  }
});

var Todo = React.createClass({
  render: function() {
    return <div>{this.props.todo.text}</div>;
  }
});

http://jsfiddle.net/ghmpo42k/6/

Unfurtunatly this does not work yet because of an unhandled case that does not allow to set multiple classes at the same time. Will mention that on the React issue so that it is supported in the future.

In the meantine, you can simply copy the ReactCSSTransitionGroup and solve the bug yourself :)

0
João Paulo Motta On

Just find a solution for that.

It's not working 100% smoothly but it looks really nice in some components:

events = this.props.schedule.map(function(event) {
    return (
        <li className="animated" key={event.time}>
           <ScheduleEventItem event={event} />
        </li>
    );
});


return (
                <React.addons.CSSTransitionGroup className="animated" 
                    transitionName={{enter: "flipInX", leave: "flipOutX"}}
                    transitionEnterTimeout={1000} transitionLeaveTimeout={1}
                    >
                        {events}
                </React.addons.CSSTransitionGroup>
);

Put the animated class on the child elements.

It's also important to keep the transitionEnterTimout at 1000. That's the time it takes for the animate.css animation to run. React needs to know that. I've set the transitionLeaveTimeout to 1 because I didn't care about the leaveAnimation. You will probably have to tweak this to your needs.

0
Vishal Sharma On

An old thread but I think I have an easy, straight forward solution for this.

I did it in this way, I downloaded the animate.css from the provider and wrote my styles.css importing animate.css as below.

@import "lib/animate.css";

.headerForm-enter {
    animation: 0.8s flipInX ease;
}

.headerForm-leave {
    animation: 0.5s flipOutX ease;
}

Note that I'm using the animations of animate.css in the react generated class. The ReactCSSTransitionGroup is as below.

<ReactCSSTransitionGroup
    transitionName='headerForm'
    transitionEnterTimeout={800}
    transitionLeaveTimeout={500}>
    {content}
</ReactCSSTransitionGroup>
0
Matt On

Sebastien, you were on was on the right track, but I think you've misunderstood enter vs enterActive:

Working fiddle:

http://jsfiddle.net/mjv2y58o/

<ReactCSSTransitionGroup transitionName={{enter: "animated", enterActive: "bounce", leave: "animated",leaveActive: "tada"}}>

Your proposal to allow multiple classnames is still valid, as it would be useful for utility classes such as infinite, but it isn't required to get Animate.css working with react 0.14.

However, many of Animate.css's entry animations don't play nice with React, particularly in Safari. There is a brief delay after the component is added to the dom and before the animation starts, so on entry, you will get a flash of the component, before it gets hidden and animated into view.

0
Luca Faggianelli On

I struggled a bit to make it working with a newer version of react-transition-group (v4.x.x), at the end this is the code:

Note: I'm using animate.css v4 and class names are slightly different than v3

import { CSSTransition } from 'react-transition-group'

const [ showControls, setShowControls ] = useState(false)

<CSSTransition
  in={showControls}
  timeout={400}
  unmountOnExit
  classNames={{
    enter: 'animate__animated',
    enterActive: 'animate__fadeInUp',
    exit: 'animate__animated',
    exitActive: 'animate__fadeOutDown'
  }}
>
  <div />
</CSSTransition>

I'm using the above code to show control buttons on mouse move and hide them after a timeout and the unmountOnExit prop is very important for hiding the component after its exit transition