Peter Ekene Eze Learn, Apply, Share

Implementing animations in React with React Spring

5 min read 1651

Animations in React

Animations has evolved to very complicated UI element manipulations. They are used to increase interactivity on web pages and to give users an engaging experience while using websites. Developers are constantly looking to find better ways to implement animations without causing a major performance bottleneck.

Animation effects are applied on the UI thread which is usually called frequently, as a result, adding certain animations/animation libraries could have negative impacts on your site. This is why we have chosen to discuss React Spring as a tool you should consider using to animate your React apps.

React Spring

React Spring is a spring-physics based animation library that powers most UI related animation in React. Given the performance considerations of animation libraries, React Spring is the best of two worlds. It is a bridge on the two existing React animation libraries; React Motion and Animated. It inherits animated powerful interpolations and performance while maintaining react-motion’s ease of use.

Having understood what React Spring is, and what it offers, let’s take a look at how we can use it to build seamless animations in React applications. We’ll explore its features to better understand its strengths.

Prerequisites

Before we go any further, this article assumes the following:

Getting started with React Spring

The best way to add React Spring to your application will be via the package managers. Simply open a terminal window on your project’s root directory and run the installation command below:

npm install react-spring
#OR
yarn add react-spring

This makes React Spring available in your application’s node_modules folder where you can import it from.

import react-spring from 'react-spring'

With the introduction of hooks in React, you can add state to functional components. React Spring takes this up a notch by providing a hook based API which allows you to define and convert data that you would generally pass as props to animated data.

To better demonstrate some of the features of React Spring, let’s take a closer look at the available hooks in the React-spring module. There are five major hooks available in React Spring at the moment:

  • useSpring — A single spring, moves data from a to b
  • useSprings — Multiple springs mainly for lists, where each spring moves data from a -> b
  • useTrail — Multiple springs with a single data set, one spring follows or trails behind the other
  • useTransition — For mount/unmount transitions (lists where items are added/removed/updated)
  • useChain — To queue or chain multiple animations together

For each of these hooks, there are several animation effects you can implement, it’s limitless and goes as far as your imagination will take you. We’ll look at some use cases for useSpring , useSprings and useTrail to demonstrate how you can implement them in your React applications.

useSpring

useSpring is one of the simplest React Spring hooks. It turns defined values into animated values. It does this in two ways, either by overwriting the existing props with a different set of props on component re-render or by passing an updater function that returns a different set of props that is then used to update the props using set.

Import it into the needed component like so, since we’ll be using the hooks API in this explanation:

import {useSpring, animated} from 'react-spring'

Here are the two methods for using the useSpring hooks:

1) Overwriting existing props

const props = useSpring({opacity: toggle ? 1 : 0})

Here, if you re-render the component with changed props, the animation will update automatically.

2) Passing an updater function

In this case, there is no re-rendering. This method is mostly applied for fast occurring updates. It also has an optional argument (stop) to stop animation.

const [props, set, stop] = useSpring(() => ({opacity: 1}))
    // Update spring with new props
    set({opacity: toggle ? 1 : 0})
    // Stop animation
    stop()

Since we are animating, we would be moving data from one state to another. Spring naturally comes with two props: from and to to show the initial position and the end position of the animation.

We will discuss this further when explaining the render-in-props API. Now, to get a feel of how the useSpring hook API works, here’s a small demo that shows a simple animated greeting card for a landing page:

clickable elements in react spring

On CodeSandbox:

From the demo above we can see that the first few lines of code express the initial state and the final position of the box we are trying to animate:

const contentProps = useSpring({
opacity: greetingStatus ? 1 : 0,
marginTop: greetingStatus ? 0 : -500
});

In this example, the content slides in from the top of the page down to the center. The value of -500 marginTop is to set the position off-screen, then define an opacity of 0 as our values for the from prop. We do this to achieve a certain appearance of the box. These values are assigned to contentProps which we then pass as props to animated.div like so:

<a.div className="box" style={contentProps}>
<h1>Hey there ! React Spring is awesome.</h1>
</a.div>

useSprings

useSprings is just like useSpring, the only difference is that it is used to create multiple springs, each with its own config. It is mostly used for lists, where each spring moves data from an initial state to a final state. This also provides us with two options on how to implement. Since we are working with multiple values, this method works in two forms.

Overwrite values to change the animation

Here, the animation is updated to each element by triggering a props change. It is simply achieved like this:

const springs = useSprings(number, items.map(item => ({ opacity: item.opacity }))

From the snippet above, we can see that the list items are mapped to have the useSpring method act on each element. That way, we can trigger the animation to happen on each element.

Pass a function that returns values, and update using “set”

You will get an updater function back. It will not cause the component to render like an overwrite would (still the animation will execute, of course). Handling updates like this is most useful for fast-occurring updates.

const [springs, set, stop] = useSprings(number, index => ({opacity: 1}))
// Update springs with new props
set(index => ({opacity: 0}))
// Stop all springs
stop()

How do we use this? Imagine we have a list of people and we wanted a user to know exactly which person is being selected, a cool way to bring more life to this would be to explore this demonstration by Paul Henschel.

list of people using react spring

On CodeSandbox:

useTrail

useTrial enables us to create multiple springs with a single configuration. It has almost the same configuration as useSpring with a variation in the implementation. It animates the first item of a list of elements while the rest of the elements form a natural trail and follow their previous sibling:

return trail.map(props => <animated.div style={props} />)

It takes a list of items of any type and their keys. The latter defaults to item => item, however, if your items are self-sufficient as a key, it’ll often be good enough.

On CodeSandbox:

const config = { mass: 5, tension: 2000, friction: 200 };

The above line in the demo configures the common API of spring to set the default values of the parameters.

const trail = useTrail(items.length, {
config,
opacity: toggle ? 1 : 0,
x: toggle ? 0 : 20,
height: toggle ? 80 : 0,
from: { opacity: 0, x: 20, height: 0 }
});

The above snippet uses the listed props to set the initial and final conditions of the elements using the ternary operators to indicate the switch.

Render-props API

This method of implementing React Spring in projects was used in class components which was the default mode before React Hooks were introduced in React v16.8. For the sake of inclusiveness, let’s also explore it to accommodate developers on the older version of React. With this method, the importation into projects is a bit different.

Spring

The class component implementation of animating a single element using React Spring would use spring as opposed to useSpring. As a result, we would import it into projects like so:

import {Spring} from 'react-spring/renderprops'

As we mentioned earlier, Spring/useSpring makes use of two props from and to to show the initial position and the end position of the animation like so:

<Spring
  from={{ opacity: 0 }}
  to={{ opacity: 1 }}>
  {props => <div style={props}>hello</div>}
</Spring>

Trail

In this case, we are dealing with the class component equivalent of useTrail and it is imported as:

import {Trail} from 'react-spring/renderprops'

The working principle remains the same however, the mode of transformation becomes:

<Trail items={items} keys={item => item.key} from={{transform: 'translate3d(0,-40px,0)'}} to={{transform: 'translate3d(0,0px,0)'}}>
  {item => props => <span style={props}>{item.text}</span>}
</Trail>

We can notice new props being used in the example above. They behave like keys that are being used to specify what item the animation is being carried out on. You can find more examples of props being accepted by trial in the docs examples.

The performance advantage of React Spring

The main advantage of React Spring over other animation libraries is its ability to apply animations without relying on React to render updates frame by frame. This advantage is usually noticed when dealing with nested routes or charts. For more information on the implementation of specific performance boosts, check out the official documentation.

Conclusion

In this article, we have analyzed some use cases using React Spring’s Hooks API and also explored the class component equivalents. Seeing the performance advantage and simple syntax of React Spring, I would strongly recommend using this in your projects as smooth animations help in ensuring awesome user experiences.

 

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, tracking slow network requests and component load time, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors performance of your app with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps - .

Peter Ekene Eze Learn, Apply, Share

Leave a Reply