I'm SPRUNG!
Yes this series is named after the 2005 song by T-Pain...
What is React Spring?
React Spring is a spring-physics based animation library. Instead of manipulating time, we give our elements mass, tension, and friction to mimic how things move from one position to another in real life.
Ok then... so how do we actually animate things?
First we have to get a few things out of the way.
1. The animated
component
We can only animate animated
components, these are provided by the react-spring
library. We can also use a
to denote an animated component as well
import { animated, a } from '@react-spring/web'
<animated.div /> // will animate
<span /> // won't animated
<a.h2 /> // will animate
2. We define our springs in two ways:
- As an config object
- Or as an anonymous function passed into the hook
// This spring will run when the component mounts
const spring = useSpring({
from: {opacity: 0, 'translateY(100%)'},
to: {opacity: 1, 'translateY(0)'}
})
// This spring will run based on state
const [active, setActive] = useState(false)
const spring = useSpring({
opacity: active ? 1 : 0,
transform: active ? 'translateY(0%)' : 'translateY(100%)'
})
/*
And lastly we can use an imperative method. We use array
destructuring to receive a controller object. We just need
to pass an anonymous function with our config object.
This method doesn't rely on the components lifecycle.
*/
const [styles, api] = useSpring(() => ({
opacity: 0,
transform: 'translateY(100%)'
}));
api.start(({
opacity: 1,
transform: 'translateY(0%)'
}))
Our first animation
const [active, setActive] = useState(false)
const spring = useSpring({
opacity: active ? 1 : 0,
transform: active ? 'translateY(0%)' : 'translateY(100%)'
})
const handleClick = () => {
setActive(state => !state)
}
return (
<a.p style={spring}>Poof!<a.p>
<button onClick={handleClick}>Click Me!</button>
)
Above we see that the spring will only trigger based on the state of active
. By default it will be invisible, and its starting position will be 100% of its origin on the Y axis (this means it will animate bottom - up). We've also passed the whole spring. But we can also use the spread operator...
return (
<a.p {...spring}>Poof!<a.p>
<button onClick={handleClick}>Click Me!</button>
)
Our second animation
But what if we want to apply this spring to multiple elements in an array? React-spring has a dedicated hook for that useSprings
, which we'll cover in the next post, but we can actually use the useSpring
hook to do this, although it will be limited. All we have to do is map over the array and apply it to each rendered jsx element
/*
Lets say we have four boxes we want to spin and turn into
circles
*/
const Example = () => {
const [active, setActive] = useState(false)
const elements = ['Item 1', 'Item 2', 'Item 3', 'Item 4']
const animation2 = useSpring({
transform: isActive ? 'rotate(720deg)' : 'rotate(0deg)',
borderRadius: isActive ? '50% 50%' : '0% 0%',
backgroundColor: isActive ? '#FF7518' : 'rgb(255, 255, 255)',
color: isActive ? 'rgb(255, 255, 255)' : 'rgb(0, 0, 0)',
transformOrigin: 'center',
});
const handleClick = () => {
setActive(state => !state)
}
return (
{elements.map(el => <a.p style={spring}>{el}<a.p>)}
<button onClick={handleClick}>Click Me!</button>
)
}
This is nice if you simply want all the elements to have the same animation all happening at once.
Conclusion
Things to note about the useSpring
hook:
Components will reverse their animation when tied to a state variable. If using the imperative method, springs will jump from the end state to the beginning position and run again
Remember that your components, even if their opacity is set to 0, they are still mounted on the DOM. They're never unmounted. We will take a look at mounting and un-mounting elements using the
useTransition
hook in the future
This wraps up the first part of the react-spring series! So stay tuned for part 2 on the useSprings
hook!
Top comments (0)