Written by Peter Ekene Eze✏️
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:
- Node.js ≥v6 is installed on your machine
- npm is installed on your machine
- You have a basic understanding of React.js
- You have a basic understanding of React hooks
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:
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.
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.
Editor's note: Seeing something wrong with this post? You can find the correct version here.
Plug: LogRocket, a DVR for web apps
LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
Try it for free.
The post Implementing animations in React with React Spring appeared first on LogRocket Blog.
Top comments (4)
That was a great article, but how come no
useTransition()
?I'm just stuck on that one right now 🤔 I can get all the rest working in my project but that one.
For now...
Hi, Brian,
Would you check CodeSandbox sandboxes?
They seemed to fail to show the demos.
If the demos still fail to show, the sandboxes do work properly here: blog.logrocket.com/animations-with.... Thanks for pointing that out.
Demos look great~
Thanks, Brian 🙋♂️