Reputation: 1467
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);
Upvotes: 9
Views: 20314
Reputation: 2522
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
Upvotes: 0
Reputation: 2610
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>
Upvotes: 7
Reputation: 3902
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>
);
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.
Upvotes: 2
Reputation: 3780
Sebastien, you were on was on the right track, but I think you've misunderstood enter vs enterActive:
Working fiddle:
<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.
Upvotes: 4
Reputation: 92210
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 :)
Upvotes: 3