react-with-animation
A higher-order-component (HOC) to manage short-lived CSS animations in React
Working example: here or take a quick squiz at the code example further down the readme.
Concept
Let's say you want to temporarily add a CSS class to a React component to play a little animation, and when the animation's finished, remove the class. Sounds like a simple enough thing to do, right? We've been doing that for years in jQuery:
$('#myThing').addClass('animateMe').delay(3000).removeClass('animateMe');
In React, the $('#myThing')
selector part is a bit different. Because React is declarative in nature, we need a component that can handle imperatively telling React which component we want to add (and remove) the CSS classes to. That's what this HOC does - it 'wraps' your component so that it always knows where it is in the React DOM, and can apply and remove the animation when it's done.
const AnimateMyComponent = withAnimation(MyComponent);
render() {
return <AnimateMyComponent animationClasses="animateMe" animationDuration={3000} />
}
There are plenty of ways to do this, but this HOC offers a simple, unified way to integrate such animations into your already-existing components, without needing to add change them or add all the boilerplate code each time.
Installation
npm i react-with-animation --save
Example
Check out a working example here or take a quick squiz at the code example below.
- Set up your CSS Animation
.animateMe {
animation-name: slideAndFadeIn;
}
@keyframes slideAndFadeIn {
0% {
transform: translateX(-10px);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
- Then in React,
const MyComponent = ({ className, style }) => <div className={className} style={style}>Yay</div>;
const AnimateMyComponent = withAnimation(MyComponent);
render() {
return <AnimateMyComponent animationClasses="animateMe" animationDuration={3000} animateOnFirstRender={true} />
}
- On render,
<MyComponent />
will have the CSS class animateMe
for 3000ms, then once the animation is completed, the class will be removed!
API / Props
The wrapper HOC takes the following props. These are considered to be the basic configuration
Prop | Type | Optional? | Default |
---|
animationClasses | string | no | '' |
animateOnFirstRender | boolean | yes | false |
animationDuration | number (ms) | yes | 3000 |
It is important to note that the wrappee (ie the component that will have the animation applied to it) must pass these props:
Prop | What is applied |
---|
className | animationClasses + any other classes you place on the component |
style | animationDuration + any other styles you place on the component |
Methods
startAnimation()
Will 'play' the animation again.
You will need to set a ref
and you can call ref.startAnimation();
const MyComponent = ({ className, style }) => <div className={className} style={style}>Yay</div>;
const AnimateMyComponent = withAnimation(MyComponent);
class Animated extends React.Component {
start = () => {
this.animatedComponentRef.startAnimation();
};
render() {
return (
<div>
<AnimateMyComponent animationClasses="animateMe" ref={el => this.animatedComponentRef = el } />
// Click the button and call the start() method of this class
<Button onClick={this.start}>Play</Button>
</div>
);
}
}
Gotchas
-
You should not set animation-duration
in CSS - this is handled via the animationDuration
prop set in your wrapped component.
-
You need to wrap the actual component/element that will have the css animation applied to it. If you want some <Text />
inside a div to be animated, wrap the <Text />
component in the HOC, not the parent.
License
Released under the MIT license.
Contribute
Please let me know if you have any feedback. Fork the repo, create Pull Requests and Issues. Have a look into how to contribute.