A React hook for animating components when they are mounted and unmounted (added to / removed from React tree).
- Uses Web Animation API (60fps animation off main thread)
- Spring physics based animation
- Cancelable / reversable animations
- Chainable mounts / unmounts
- Small (~1KB)
- NPM:
npm install use-animate-presence
- UMD: https://unpkg.com/use-animate-presence@latest/lib/use-animate-presence.umd.js
import { useAnimatePresence } from "use-animate-presence";
const variants = {
x: { from: -800, to: 0 },
};
export default function App() {
const animatedDiv = useAnimatePresence({
variants,
initial: "visible",
});
return (
<div>
<button onClick={() => animatedDiv.togglePresence()}>Toggle</button>
{animatedDiv.isRendered && <div ref={animatedDiv.ref} />}
</div>
);
}
Play with the code here:
useAnimatePresence
takes one object as an argument. Below is a table with possible properties and their description (some properties are explained in detail later):
Property | Default | Required | Type | Details |
---|---|---|---|---|
variants |
- | true |
object |
Properties and values to animate |
initial |
- | true |
"hidden" or "visible" |
Whether item is rendered initially |
animateFirstRender |
true |
false |
boolean |
Whether to animate on first render (first mount) |
enter |
undefined |
false |
function |
Function to execute when enter animation is finished |
exit |
undefined |
false |
function |
Function to execute when exit animation is finished |
wait |
undefined |
false |
function |
Function to execute both when enter and when exit animation is finished |
debugName |
"" |
false |
string |
Name for tracking the animation lifecycle of the hook, if not provided it won't show logs to console |
duration |
1000 |
false |
number |
Animation duration (ms) (use if you only animate opacity) |
options |
(read below) | false |
object |
Spring options (stiffness, mass and damping ratio) |
useAnimatePresence
returns an object which contains a function that can toggle presence, a ref that you need to attach to the element you want to animate and a isRendered
property which you can use to conditionally render elements.
Property | Details |
---|---|
ref |
React ref |
togglePresence |
Function that toggles presence (and animates) |
isRendered |
Boolean that should be used to conditionally render elements |
Look again at the example above to see how all properties are used:
return (
<div>
<button onClick={() => animatedDiv.togglePresence()}>Toggle</button>
{animatedDiv.isRendered && <div ref={animatedDiv.ref} />}
</div>
);
Variants look like this:
const variants = {
x: { from: -800, to: 0 },
deg: 360,
};
Except for deg
, which is degrees of rotation, every property must have a from
value and a to
value. All possible properties are: x
, y
, deg
, opacity
and scale
(scale
is experimental and might not work as intended).
These are callbacks to be executed after enter
(mount) or exit
(unmount) animation finishes. wait
is simply a shorthand - if you need to execute the same callback on both enter
and exit
animations you can just pass it as a wait
property. Mostly, you will need this to chain mounts / unmounts. For example, if you want element B to animate only after element A is finished, you can do this:
const elementA = useAnimatePresence({
variants: springVariants,
initial: "hidden",
debugName: "front-square",
});
const elementB = useAnimatePresence({
variants: springVariants,
initial: "visible",
wait: elementA.togglePresence,
});
return (
<>
{<button onClick={() => elementB.togglePresence()}>Toggle</button>}
{elementB.isRendered && (
<div ref={elementB.ref}>
{elementA.isRendered && <div ref={elementA.ref} />}
</div>
)}
</>
);
In this example, elementA
will not be animated and its property isRendered
will be false until elementB
is finished animating. Play with a complex example here:
Springs have stiffness, mass and damping ratio. The defaults are: stiffness 150
, mass 3
and damping 27
. You can customize the parameters like this:
useAnimatePresence({
variants,
initial: "visible",
options: {
stiffness: 500,
mass: 1,
damping: 10,
},
});
You can easily create nice toast notifications with this library.
Code:
You can render an arbitrary array of items that are animatable with useAnimatePresence
. Here is something you can achieve if you combine this library with react-easy-flip.
Code:
This library requires React version 16.8.0 or higher (the one with Hooks).
Any kind of contribution is welcome!
- Open an issue or pick an existing one that you want to work on
- Fork this repository
- Clone your fork to work on it locally
- Make changes
- Run
yarn build
and make sure that it builds without crash - Push changes and open a pull request
Note: if you want to link the package to some other project to do integration tests, you may run into an issue with two React versions. In this case, run npm link <path-to-react-in-your-other-project>
while in use-animation-presence
root directory.