You want to show a dialog to visitor to ask your user a question. How do you want to do it?
- Just show up the dialog from no where.
- Fade in the dialog from middle of website until it is fully visible.
I guess that you already choose the second option. This approach will bring the best experience for your visitor and your website appears more professional. And this is an animation. How do we create animation in React?
There many solutions to bring animation to React application. You can just use CSS3 to create animation effect, but you won’t have much control in the animation process. Another option would be ReactTransitionGroup, this library helps you to control the animation for entering and leaving event.
But it is hard to control the animation process if the animation time, distance and duration are dynamic or depend on user input. Still with these approaches, you still have to use CSS to create animation, modifying the css or update css class name is cumbersome and hard to maintain
Fortunately, there is an excellent library which is React-Move. React-Move doesn’t create the animate itself, but it provides some components help you create animation easier. Depend on your data and duration, it will output the data at the animation time and you can use JSX to create animation.
Let’s see how do we use this library.
Animate a single object
We can animate a single object with <Animate /> component. Here is an example:
In this example, when you click on the Hello button, it will changes the state of that component and make the button move. This is the source code:
import React, { Component } from 'react'; import { Animate } from 'react-move'; import _ from 'lodash'; export default class Hello extends Component { constructor(props) { super(props); this.state = { left: 0, color: 'blue', duration: 300 }; } toggleButtonPosition = () => { let left = 0; if (!this.state.left || this.state.left === 0) { left = Math.random() * 300 + 50; } let duration = Math.random() * 300 + 200; let color = _.sample(['red', 'blue', 'black', 'green']); this.setState({ left, color, duration }) } render() { let { left, color, duration } = this.state; return ( <div> <Animate data={{ left: left, color: color }} default={{ left: 0, color: 'blue' }} duration={duration} easing='easeQuadIn' > {data => ( <div style={{ transform: `translate(${data.left}px, 0)`, background: data.color || 'blue', position: 'absolute', width: 50, height: 50, display: 'flex', justifyContent: 'center', alignItems: 'center', borderRadius: 10, color: 'white', cursor: 'pointer' }} onClick={this.toggleButtonPosition} > Hello </div> )} </Animate> </div> ); } }
In this component, we initiate its state with left equals 0, color equals “blue” and duration equals 800. These data is stored into component state and also passed into Animate component.
The children of <Animate /> component is a function which provides animation data. We use this animation data and inject into style property of the <div> element. Exactly, we modify the transform property of <div> element.
It’s really easy to use <Animate /> component, right? Now we are moving to <Transition /> component
Animate an array of objects
So it’s easy to animate an object, how about an array of objects. How do we create animation for entering and leaving event. To answer this question, React-Move provides <Transition /> component. The usage of <Transition /> is similar to <Animate />, but <Transition /> also has other property to control the enter, update and leave event of each item:
- update: a function which returns the state of item after it has been entered the list.
- enter: a function which returns the state of item when it is entering the list.
- leave: a function which returns the state of item when it is leaving the list
- getKey: a function to return the unique identity for element in the list.
- stagger: the delay value for each item relatives to preceding item.
Here is an example of <Transition />
In the example, when click the Toggle button, it will hide and show the items. Because of the stagger property, each item will have a small delay time relatives the preceding item.
Here is the source code:
import React from 'react'; import { Transition } from 'react-move'; import _ from 'lodash'; export default class Hello extends React.Component { constructor(props) { super(props); this.state = { items: this.makeItems() } } toggleItems() { if (this.state.items && this.state.items.length > 0) { this.setState({ items: [] }); } else { this.setState({ items: this.makeItems() }); } } makeItems() { let items = []; for (let i = 0; i < 10; i++) { items.push(i); } return items; } render() { let {items} = this.state; return ( <div> <div onClick={this.toggleItems.bind(this)}>Toggle</div> <Transition data={items} getKey={d => d} update={d => ({ translate: 0, opacity: 1 })} enter={d => ({ translate: -1, opacity: 0 })} leave={d => ({ translate: 1, opacity: 0 })} stagger={200} > {dataArray => ( <div> {dataArray.map(data => ( <div key={data.key} style={{ transform: `translate(${100 * data.state.translate}px, ${20 * data.key}px)`, opacity: data.state.opacity }}>{data.key}</div> )) } </div> )} </Transition> </div> ); } }
Still, inside of <Transition /> component is an function which provides an array of data. We have to loop through this array to extract animation value for each object.
Conclusion
Compare to other animation solution in React, so far React-Move the most convenient and powerful library. I am going to use it in my next projects.
Tell me your opinion in the comment section.