Adding animations to Components with react-spring

Cover Image for 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