Adding animations to Components with react-spring
This week, over at upwork, there was a job lisiting to build a site with Frontity, who would support a certain "no load" effect. Personally, one of the things I like about creating websites with React, is that effect where you wouldn't load a newpage when you click on a link - instead the components who are visible to the user would just be replaced.
After seeing that job description, I thought maybe I could read something about it or atleast learn how to to implement that on my personal portfolio, to make the page transitions a bit smoother.
Animation Libraries
In general I was planning to add two different transitions: on the initial page load and when clicking on a link.
But what (popular animations libraries do exist already for using in React? After a bit of research I came accross about the following:
- react-spring
- Framer Motion
- React Transition Group
- React-Motion
- React Move
In the end I decided to go with react-spring - one of the reasons was because there were already a few examples over at https://community.frontity.org/.
Implementing react-spring
Getting started with react spring for basic use cases is quite easy - Install it via NPM:
npm install react-spring
After that I just imported it, created the animation-configuration and wrapped the animated elements into a <animated.div />:
import { useSpring, animated } from 'react-spring' ... const props = useSpring({ opacity: 1, from: { opacity: 0 } }) <animated.div style={props}> ... </animated.div>
import { useSpring, animated } from 'react-spring'
...
const props = useSpring({
opacity: 1,
from: { opacity: 0 }
})
<animated.div style={props}> ... </animated.div>
To edit the transition speed some configuration like this is needed:
const props = useSpring({ opacity: 1, from: { opacity: 0 }, config: { duration: 2000} })
const props = useSpring({
opacity: 1,
from: { opacity: 0 },
config: { duration: 2000}
})
That's already it? Unfortunately not. I had to realize that all the changes on the <Switch> element (which is used to switch between all the pages on the site) wouldn't be affected, so we would have only achieved one of the two use cases I wanted to implemented with animations
useTransition
To achieve the animations on Links we would need to implement it, with use-transition. Over at the documention it is described as the following:
"An animated TransitionGroup. Feed it your items, keys (which can be null if items are atomic), and lifecycles. Whenever items are added or removed, it will animate these changes."
https://www.react-spring.io/docs/hooks/use-transition
The Implementation would look like this, where the router link is used as key and we need a Absolute box (because otherwise all the box elements could be displayed as smoothly):
But now when clicking on the Links, the Pages would not load an the console would prompt a "Uncaught TypeError: Cannot read property 'map' of undefined"
Solution: As we were already querying the data from the state before the Switch, we wouldn't need to do that in the corresponding components. The Problem was fixed with doing the following things:
- Pass the data to the component using data={data}
- Consume the passed values, and remove the State-Query:
That's it - now my site was using the animations correctly 🎉
Sources that helped to achieve this:
- https://community.frontity.org/t/possible-to-do-page-transitions/526/8
- https://github.com/jcklpe/desert-jackalope