- Notifications
You must be signed in to change notification settings - Fork649
An easy way to perform animations when a React component enters or leaves the DOM
License
reactjs/react-transition-group
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
A fork, and "drop in" replacement for the original React TransitionGroup addons. Eventually this package can supercede the original addon, letting the React team focus on other stuff and giving these components a chance to get the attention they deserve out on their own. See:facebook/react#8125 for more context.
A ton of thanks to the React team, and contributors for writing and maintaining these components for so long!
TheTransitionGroup add-on component is a low-level API for animation, andCSSTransitionGroup is an add-on component for easily implementing basic CSS animations and transitions.
The recommended installation method is through eithernpm oryarn.
# npmnpm install react-transition-group@1.x --save# yarnyarn add react-transition-group@1.x
Since react-transition-group is fairly small, the overhead of including the library in your application isnegligible. However, in situations where it may be useful to benefit from an external CDN when bundling, linkto the following CDN:
https://unpkg.com/react-transition-group/dist/react-transition-group.min.js
CSSTransitionGroup is a high-level API based onTransitionGroup and is an easy way to perform CSS transitions and animations when a React component enters or leaves the DOM. It's inspired by the excellentng-animate library.
Importing
import{CSSTransitionGroup}from'react-transition-group'// ES6varCSSTransitionGroup=require('react-transition-group/CSSTransitionGroup')// ES5 with npm
classTodoListextendsReact.Component{constructor(props){super(props);this.state={items:['hello','world','click','me']};this.handleAdd=this.handleAdd.bind(this);}handleAdd(){constnewItems=this.state.items.concat([prompt('Enter some text')]);this.setState({items:newItems});}handleRemove(i){letnewItems=this.state.items.slice();newItems.splice(i,1);this.setState({items:newItems});}render(){constitems=this.state.items.map((item,i)=>(<divkey={item}onClick={()=>this.handleRemove(i)}>{item}</div>));return(<div><buttononClick={this.handleAdd}>Add Item</button><CSSTransitionGrouptransitionName="example"transitionEnterTimeout={500}transitionLeaveTimeout={300}>{items}</CSSTransitionGroup></div>);}}
Note:
You must provide the
keyattribute for all children ofCSSTransitionGroup, even when only rendering a single item. This is how React will determine which children have entered, left, or stayed.
In this component, when a new item is added toCSSTransitionGroup it will get theexample-enter CSS class and theexample-enter-active CSS class added in the next tick. This is a convention based on thetransitionName prop.
You can use these classes to trigger a CSS animation or transition. For example, try adding this CSS and adding a new list item:
.example-enter {opacity:0.01;}.example-enter.example-enter-active {opacity:1;transition: opacity500ms ease-in;}.example-leave {opacity:1;}.example-leave.example-leave-active {opacity:0.01;transition: opacity300ms ease-in;}
You'll notice that animation durations need to be specified in both the CSS and the render method; this tells React when to remove the animation classes from the element and -- if it's leaving -- when to remove the element from the DOM.
CSSTransitionGroup provides the optional proptransitionAppear, to add an extra transition phase at the initial mount of the component. There is generally no transition phase at the initial mount as the default value oftransitionAppear isfalse. The following is an example which passes the proptransitionAppear with the valuetrue.
render(){return(<CSSTransitionGrouptransitionName="example"transitionAppear={true}transitionAppearTimeout={500}transitionEnter={false}transitionLeave={false}><h1>Fading at Initial Mount</h1></CSSTransitionGroup>);}
During the initial mountCSSTransitionGroup will get theexample-appear CSS class and theexample-appear-active CSS class added in the next tick.
.example-appear {opacity:0.01;}.example-appear.example-appear-active {opacity:1;transition: opacity.5s ease-in;}
At the initial mount, all children of theCSSTransitionGroup willappear but notenter. However, all children later added to an existingCSSTransitionGroup willenter but notappear.
Note:
The prop
transitionAppearwas added toCSSTransitionGroupin version0.13. To maintain backwards compatibility, the default value is set tofalse.However, the default values of
transitionEnterandtransitionLeavearetrueso you must specifytransitionEnterTimeoutandtransitionLeaveTimeoutby default. If you don't need either enter or leave animations, passtransitionEnter={false}ortransitionLeave={false}.
It is also possible to use custom class names for each of the steps in your transitions. Instead of passing a string into transitionName you can pass an object containing either theenter andleave class names, or an object containing theenter,enter-active,leave-active, andleave class names. If only the enter and leave classes are provided, the enter-active and leave-active classes will be determined by appending '-active' to the end of the class name. Here are two examples using custom classes:
// ...<CSSTransitionGrouptransitionName={{enter:'enter',enterActive:'enterActive',leave:'leave',leaveActive:'leaveActive',appear:'appear',appearActive:'appearActive'}}>{item}</CSSTransitionGroup><CSSTransitionGrouptransitionName={{enter:'enter',leave:'leave',appear:'appear'}}>{item2}</CSSTransitionGroup>// ...
In order for it to apply transitions to its children, theCSSTransitionGroup must already be mounted in the DOM or the proptransitionAppear must be set totrue.
The example below wouldnot work, because theCSSTransitionGroup is being mounted along with the new item, instead of the new item being mounted within it.
render(){constitems=this.state.items.map((item,i)=>(<divkey={item}onClick={()=>this.handleRemove(i)}><CSSTransitionGrouptransitionName="example">{item}</CSSTransitionGroup></div>));return(<div><buttononClick={this.handleAdd}>Add Item</button>{items}</div>);}
In the example above, we rendered a list of items intoCSSTransitionGroup. However, the children ofCSSTransitionGroup can also be one or zero items. This makes it possible to animate a single element entering or leaving. Similarly, you can animate a new element replacing the current element. For example, we can implement a simple image carousel like this:
importCSSTransitionGroupfrom'react-transition-group/CSSTransitionGroup';functionImageCarousel(props){return(<div><CSSTransitionGrouptransitionName="carousel"transitionEnterTimeout={300}transitionLeaveTimeout={300}><imgsrc={props.imageSrc}key={props.imageSrc}/></CSSTransitionGroup></div>);}
You can disable animatingenter orleave animations if you want. For example, sometimes you may want anenter animation and noleave animation, butCSSTransitionGroup waits for an animation to complete before removing your DOM node. You can addtransitionEnter={false} ortransitionLeave={false} props toCSSTransitionGroup to disable these animations.
Note:
When using
CSSTransitionGroup, there's no way for your components to be notified when a transition has ended or to perform any more complex logic around animation. If you want more fine-grained control, you can use the lower-levelTransitionGroupAPI which provides the hooks you need to do custom transitions.
Importing
importTransitionGroupfrom'react-transition-group/TransitionGroup'// ES6varTransitionGroup=require('react-transition-group/TransitionGroup')// ES5 with npm
TransitionGroup is the basis for animations. When children are declaratively added or removed from it (as in theexample above), special lifecycle hooks are called on them.
componentWillAppear()componentDidAppear()componentWillEnter()componentDidEnter()componentWillLeave()componentDidLeave()
TransitionGroup renders as aspan by default. You can change this behavior by providing acomponent prop. For example, here's how you would render a<ul>:
<TransitionGroupcomponent="ul">{/* ... */}</TransitionGroup>
Any additional, user-defined, properties will become properties of the rendered component. For example, here's how you would render a<ul> with CSS class:
<TransitionGroupcomponent="ul"className="animated-list">{/* ... */}</TransitionGroup>
Every DOM component that React can render is available for use. However,component does not need to be a DOM component. It can be any React component you want; even ones you've written yourself! Just writecomponent={List} and your component will receivethis.props.children.
People often useTransitionGroup to animate mounting and unmounting of a single child such as a collapsible panel. NormallyTransitionGroup wraps all its children in aspan (or a customcomponent as described above). This is because any React component has to return a single root element, andTransitionGroup is no exception to this rule.
However if you only need to render a single child insideTransitionGroup, you can completely avoid wrapping it in a<span> or any other DOM component. To do this, create a custom component that renders the first child passed to it directly:
functionFirstChild(props){constchildrenArray=React.Children.toArray(props.children);returnchildrenArray[0]||null;}
Now you can specifyFirstChild as thecomponent prop in<TransitionGroup> props and avoid any wrappers in the result DOM:
<TransitionGroupcomponent={FirstChild}>{someCondition ?<MyComponent/> :null}</TransitionGroup>
This only works when you are animating a single child in and out, such as a collapsible panel. This approach wouldn't work when animating multiple children or replacing the single child with another child, such as an image carousel. For an image carousel, while the current image is animating out, another image will animate in, so<TransitionGroup> needs to give them a common DOM parent. You can't avoid the wrapper for multiple children, but you can customize the wrapper with thecomponent prop as described above.
componentWillAppear(callback)
This is called at the same time ascomponentDidMount() for components that are initially mounted in aTransitionGroup. It will block other animations from occurring untilcallback is called. It is only called on the initial render of aTransitionGroup.
componentDidAppear()
This is called after thecallback function that was passed tocomponentWillAppear is called.
componentWillEnter(callback)
This is called at the same time ascomponentDidMount() for components added to an existingTransitionGroup. It will block other animations from occurring untilcallback is called. It will not be called on the initial render of aTransitionGroup.
componentDidEnter()
This is called after thecallback function that was passed tocomponentWillEnter() is called.
componentWillLeave(callback)
This is called when the child has been removed from theTransitionGroup. Though the child has been removed,TransitionGroup will keep it in the DOM untilcallback is called.
componentDidLeave()
This is called when thewillLeavecallback is called (at the same time ascomponentWillUnmount()).
A derivative of "Animation Add-Ons" by the React authors and contributors, used underCC BY.
About
An easy way to perform animations when a React component enters or leaves the DOM
Resources
License
Uh oh!
There was an error while loading.Please reload this page.