React Spring Tutorial: Making Animated React Apps In 2024

Find out how to create eye-catching animations with React Spring. Discover its advantages and disadvantages, as well as alternatives.

alt

Incorporating animation into UI design can be a tricky thing. Studying the React Spring library can make people face the opposite problem. Although its documentation is well-ordered, detailed, easy to use, and has a lot of impressive examples, most of them need to be simplified if you aim to get the basics.

This React Spring tutorial will be useful to those who are just starting. We’ll look over various methods for combining multiple springs for more complicated animations, examples included. Note that a basic knowledge of React is required to understand this article. Knowing how to use styled-components/emotion/other similar libraries will also be helpful.

What is React Spring?

React and Spring is a powerful animation library for React applications, enabling you to create fluid, interactive animations. It’s prized for its ease of use, high performance, and versatility in building engaging user interfaces.

It provides a spring-physics-based animation system that allows for natural-looking motion in user interfaces. You can create interactive and dynamic user experiences by animating components based on user interactions or changes in the application state. React Spring animation is commonly used for smooth transitions, gestures, and animations in web applications.

The Role of Animations in Modern Web Development

Animations play a crucial role in web development by enhancing user experience, guiding user attention, and providing visual feedback. They make interfaces more engaging, intuitive, and enjoyable to use. Animations made with React Spring can convey information, signify changes in state, and create seamless transitions between different parts of a web application. In essence, they contribute to creating a more dynamic and interactive user interface, ultimately improving usability and user satisfaction.

The role of animations in modern web development includes:

  • Enhancing user experience
  • Guiding user attention
  • Providing visual feedback
  • Making interfaces more engaging
  • Conveying information
  • Signifying changes in the state
  • Creating seamless transitions

Principles of React Spring

  1. Physics-based animations: Using real-world physics principles to create natural and fluid motion.
  2. Spring-based animations: Utilizing spring physics to achieve smooth and responsive animations.
  3. Hooks-based API: Leveraging React’s Hooks API for managing animation state and lifecycle.
  4. Performance optimization: Optimizing performance by using requestAnimationFrame and other techniques.
  5. Declarative syntax: Employing a declarative syntax for defining animations, making code easier to read and maintain.
  6. Interpolation: Providing seamless interpolation between animation values.
  7. Chaining and sequencing: Allowing animations to be chained or sequenced together for complex effects.
  8. Accessibility and responsiveness: Ensuring animations are accessible and responsive across different devices and screen sizes.

Setting Up and Configuring React Spring

Setting up and configuring React Spring involves a few steps:

Installation: Begin by installing the library via npm or yarn.

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

Importing: Import the necessary components from React and Spring into your project:

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

Using hooks: Utilize React Spring hooks, like useSpring, to manage the animation state:

const props = useSpring({ opacity: 1, from: { opacity: 0 } });

 Animating components: Wrap your components with the animated higher-order component to animate them:

 <animated.div style={props}>Hello, world!</animated.div>

Configuring animations: Customize animations by passing configuration options to the hooks:

const props = useSpring({ opacity: 1, from: { opacity: 0 }, config: { duration: 1000 } });

Optimizing performance: Optimize performance by refining your animations and avoiding unnecessary re-renders.

Testing: Test your animations across different devices and screen sizes to ensure accessibility and responsiveness.

By following these steps, you can effectively set up and configure React Spring for your projects.

Now, let’s switch to the React Spring examples, starting with hooks.

5 hooks of the React Spring library 

React Spring calculates all the mechanics behind the scenes for nice and smooth animation and allows one to configure it for a user both partially and completely. What’s more, the library makes it easier than using pure CSS (at least, without an insanely complicated and hard-to-maintain bulk of code). 

At the moment, the React and Spring library contains 5 hooks:

  1. useSpring – a single animation that changes the state of the animation a => b.
  2. useSprings – multiple spring animations for lists that also change the animation state a => b.
  3. useTrail – multiple spring animations with a common data set, where each subsequent animation trails behind the previous one.
  4. useTransition – animations on mount/unmount for lists, where the elements get added, deleted and updated.
  5. useChain – used to determine the order and sequence of execution of several previously defined animations.

All these 5 hooks are similar, but each has its peculiarity. Let’s examine every one of them individually in more detail to learn how to apply them to making beautiful animations with React Spring examples.

useSpring

We’ll start this React Spring animation tutorial with the simplest hook – useSpring. It transforms the passed values into animated ones.

For the first example, we’ll create a simple animation component, that will resize and shift the backgroundPosition on click. 

First, let’s import the required hook and animated component:

import { animated, useSpring } from “react-spring”;

For animation on appearance it will be enough to indicate the following:

const springProps = useSpring({
   from: { opacity: 0, ... },
   to: { opacity: 1, ... }
 })

Spring allows animating the state changes from the initial from to the final to. 

Besides, the to prop can be omitted to make it more simple:

const springProps = useSpring({
   opacity: 1,
   from: { opacity: 0 },
 })

You can animate almost any CSS property or use arbitrary names, excluding the reserved keywords.

Next, you’ll need to pass springProps to the animated element. It’s worth mentioning though, that since the transmitted values are getting updated, they cannot be used with ordinary components or tags.

The following styled-components / emotion / etc component is required:

const AnimatedBox = styled(animated(ComponentName/TagName))`...`;

Or just any HTML tag, with the addition of the “animated” prefix: 

<animated.button>Button</animated.button>

Animated is an animation-primitive that allows you to handle the passed animated props. Animated extends the capabilities of native elements so that they can accept animated values.

What’s left is to pass the prop to the required component:

<AnimatedBox style={{springProps}} />

React Spring hooks can take almost any value or color, HTML attribute, and even a string pattern (for example, borderTop: “6px solid red”), etc. One very unfortunate limitation is that it’s impossible to transfer different properties for from and to in a single prop. That is, px must be converted to px, % => %, number => number, etc., or an error will occur.

As you can see from the example below, animation states can be destructured if the need arises. This is useful if, for example, you need to describe the animation states for several components at once, when using arbitrary names.

We’ll use useState to change the React Spring animation states. Since we pass both true and false values for animated props with the ternary operator, we don’t necessarily have to define initial from values for this particular case, but it’s better to be safe than sorry and define it anyway for error-proof. Otherwise, the prop data will be empty before making changes to the state, and animation might break or cause an unexpected result.

const [clicked, setClicked] = useState(false);
 
 const { size, ..., ...springProps } = useSpring({
   size: clicked ? 300 : 200,
   backgroundPosition: clicked ? "50% 100%" : "50% 0%",
   ...
   from: {
     size: 200,
     backgroundPosition: "50% 0%"
     ...
   }
 });

We’ll destructure the value of size (it will be needed for animating both width and height) and pass the other values, in this case, the backgroundPosition, to springProps.

It remains only to pass the animated values to our component, and, of course, change its state on click:

<AnimatedItem
  style={{ height: size, width: size, ...springProps }}
  onClick={() => setClicked(!clicked)}
/>

Now, after being clicked, the state will change from false to true, so the height and width of the component will change from 200px to 300px, and the backgroundPosition of the background element will also change from “50% 0%” to “50% 100%”.

Perhaps it’s worth mentioning the counter for the ProgressBar used in this example. Let’s complete our hook with the following line of code:

counter: clicked ? 100 : 0,

It’s important not to forget to destructure the counter, as we’ll need it outside of the springProps passed to the AnimatedItem component.

To iterate over counter values from 0 to 100, we’ll use some interpolation:

<AnimatedBox>

  {counter.to(val => Math.floor(val) + "%")}

</AnimatedBox>

To put it another way, the interpolation allows you to iterate over values of a function or of a specified range of values. Note that the interpolation transferred to the animated primitive works more efficiently and takes up less space.

Quite simple, right?

useSprings

import { animated, useSprings } from “react-spring”;

The useSprings hook is slightly different from the previous hook. It creates multiple spring animations for static lists.

In these React Spring examples, the colorful boxes are our list, which uses useSprings. useSprings takes the length of our list and determines the animation parameters for each of the list elements:

 const [springs, api] = useSprings(list.length, (index) => ({
   ...
 }));

useSprings in this example:

 const [springs, api] = useSprings(colorScheme.length, (index) => ({
   ...colorScheme[index],
   opacity: 1,
   borderRadius: "10%",
 }));

The background and color values are taken from the array of colorScheme object:

const colorScheme = [
  
  { name: "Red munsell", background: "#ec0b43",color: "#fff" }  ...
];

We will update the animation with a help of useCallback:

const handleOnClick = useCallback(() => {
  setIsHidden(!isHidden);
  api.start((index) => isHidden ? {
    opacity: 0.2, ...} : { opacity: 1, ...}
  );
}, [api, isHidden]);
<Box as="button" onClick={handleOnClick}>Click</Box>

We still got to pass the value of springs to the list of components:

<>
  {springs.map((props, i) => (
    <AnimatedItem style={props}>{props.name}</AnimatedItem>
  ))}
</>

Clicking the button will animate not one, but all the elements of useSprings.

useTrail

import { animated, useTrail, to } from “react-spring”;

useTrail allows you to create multiple spring animations with a single config, and each subsequent spring is executed after the previous one. It is used for staggered animation.

const [trail, api] = useTrail(list.length, { ... });

For this example the config looks approximately like this:

const [trail, set] = useTrail(imgList.length, () => ({
  opacity: 1, ...
  from: {
    opacity: 0, ...
  }
}));

Passing the trail into the component:

<GridContainer>
  {trail.map(({ sc, x, y, skewX, ...prop }, i) => (
    <AnimatedItem
      key={i}
      style={{
        ...prop,
        transform: to(
          [sc, x, y, skewX],
          (sc, x, y, skewX) =>
          `scale(${sc}) translate(${x}, ${y}) skewX(${skewX}deg)`
        )
      }}
      backgroundImage={`url(${imgList[i]}`}
    />
  ))}
</GridContainer>

What you should pay attention to in this React Spring tutorial is the interpolation for a set of values, which allows you to change the transform property for several transform-functions at once. It differs slightly from the single parameter interpolation:

transform: x.to(x => `translateX(${x}px)`)

But the principle is the same. As a result, we got a trail animation that changes the values of transform property (scale, translate and skewX) and opacity on appearance, and also changes the scale once again when the list container is clicked. By clicking the button, the opacity will also be changed with the help of the already familiar to us set function.

useTransition

import { animated, useTransition, useSpringRef } from “react-spring”;

useTransition allows you to create an animated transition group. It takes in the elements of the list, their keys, and lifecycles. The animation is triggered on the appearance and disappearance of the elements. 

You can use transition for arrays, to toggle between components, or for mounting/unmounting of the same component.

Let’s create a slider with the help of useTransition:

 const [[index, dir], setIndex] = useState([0, 0]);
 const transRef = useSpringRef();
 
 const transitions = useTransition(index, {
   ref: transRef,
   keys: index,
   from: {
     transform: `translate3d(${dir === 1 ? 100 : -100}%,0,0) scale(0.8)`
   },
   enter: { ... },
   leave: { ... },
 });
 
 useEffect(() => {
   transRef.start();
 }, [index]);

useSpringRef() is library’s version of useRef hook. It’s used to get access to api methods to control the animations.

The from, enter, leave properties describe the state of the current slide from from to enter on mount and from enter to leave on unmount.

Let’s pass our config to the component:

{transitions((styles, i) => (
  <Slide style={styles} background={`url(${slides[i].url}`} />
))}

The value of index and the direction of slides (dir) change on clicking the arrow controls:

<Arrow onClick={() => handleNextSlide(-1)} />
<Arrow onClick={() => handleNextSlide(1)} />

Where handleNextSlide is callback that takes direction (-1 for previous slide and 1 for next slide).

handleNextSlide allows not only changing the value of index and dir, but also resetting it after reaching the last slide.

As a result, we got a slider where the slides get mounted/unmounted, changing the values of opacity and transform when index and dir get changed. 

Control bullets are animated using the already familiar useSrings hook, so we won’t dwell on them.

useChain

useChain allows you to set the execution sequence of previously defined React Spring animation hooks. To do this, you need to use refs, which will subsequently prevent the independent execution of the animation.

import { animated, useChain, useSpringRef } from “react-spring”;

Let’s use this hook to animate the hamburger menu element. In our case, first, the useSpring animation of the MenuBar will execute, followed by useSprings animation for the list of Menu components – MenuItem.

Defining the ref for the useSpring and using the same principle, for the useSprings:

 const { ... , ...springProps } = useSpring({
   ref: springRef,
   ...
 });

All we have to do now is to define the order of execution of animations with useChain:

useChain(
   open ? [springRef, springsRef] : [springsRef, springRef],
   open ? [0, 0.25] : [0, 0.75]
 );

In these React Spring examples, if the state is open === true, then on expanding the menu the animation for the MenuBar will execute first, followed by MenuItems. If open === false, that is, on closing the menu, the execution order is reversed.

After setting the order of animations, you can also specify timeSteps – an array of values between 0-1 (1 = 1000ms) that defines the beginning and end of the animations. For example, [0, 0.25] 0 * 1000ms = 0 and 0.25 * 1000ms = 250ms.

Bonus

Here are a few bonus examples for this React Spring tutorial using the already familiar hooks:

Cards list – useSprings

Image gallery – useChain

useSpring + loop

Property use cases:

  • loop: true – repeat animation
  • Pass a function (loop: () => 3> n ++) which will be called after each loop iteration (return true to continue looping, false to stop)
  • Define a loop object (loop: {reverse: true}) for a separate customization of the loop animation. It may contain any useSpring properties, but the most interesting one is reverse: true, which prevents twitching when the loop is repeated.
import { animated, useSpring } from "react-spring";

Let’s configure the already familiar useSpring using the brand-new and shiny ✨ loop property:

const springProps = useSpring({
   loop: { reverse: true },
   from: { y: 0, rotate: 0 },
   to: { y: 100, rotate: 180 },
   config: { duration: 2500 }
 });

All that remains is to pass the config to our animated component:

<AnimatedItem style={springProps} />

That’s it! We got ourselves a seamless and easy way to configure loop animation. Can you imagine now that we couldn’t do it properly before?

Points to take away

Advantages of the React Spring library:

  • Animations are based on physics. There is no need (unless you intentionally want to) to customize duration or easing. The result is smooth, soft, and natural-looking animations.
  • Easy-to-use and clear documentation.
  • A lot of interesting and beautiful demos in the documentation + on the React Spring creator Paul Henschel’s CodeSandbox page.
  • If necessary, you can utilize a very useful set of hooks from use-gesture.
  • The library repository is continually being updated and maintained.
  • A small, but quite active community (spectrum, discord) has formed around the library.
  • Paul Henschel regularly shares interesting insights, demos, and more on his Twitter page.

Disadvantages of the React Spring library:

  • As we’ve already mentioned, another very unfortunate limitation of React and Spring is that it’s impossible to transfer different properties for from and to in a single prop. That is, px must be converted to px, % => %, number => number, etc., or an error will occur.
  • Also, the library doesn’t allow you to animate the value of auto. The documentation suggests using react-resize-aware, react-measure, etc. for these, and other purposes that require the exact height and width of a component.

React Spring Alternatives:

Framer/motion 

A production-ready motion library for React. Utilize the power behind Framer, the best prototyping tool for teams. Proudly open source. 

  • Uses a simple animation and gesture API like the Framer library, while preserving the semantics of HTML and SVG. 
  • Makes it easy to port high-precision prototypes to a production-ready environment or create something completely new. 
  • Makes it easier for developers to understand how the prototype should function.

Framer/motion is also quite popular! It has 22.5k stars on GitHub, and almost 4 million weekly downloads.

The writing of the code in Framer is an interesting and exciting process that does not require any special preparation; moreover, the program’s website has very detailed documentation with examples and tutorials.

React Transition Group

React Transition Group is not an animation library, it does not animate styles by itself. Instead, it exposes transition stages, manages classes and group elements and manipulates the DOM in useful ways, making the implementation of actual visual transitions much easier. The React Transition Group component was developed by the ReactJS community team. It allows you to implement basic CSS animations and transitions worry-free.

It needs to be installed in the package for your React app, which will slightly increase the overall build size. 

React Transition Group has 10k stars on GitHub, and almost 6k weekly downloads.

React GSAP

This library lets you use the GreenSock Animation Platform (GSAP) in React in a fully declarative way. It abstracts away the direct use of the GSAP Tween and Timeline functions. If you’d like to learn about GSAP tutorials for beginners, pick into our standalone article on the topic

React GSAP has over 550 stars on GitHub and 5.7k weekly downloads.

Conclusion

Mastering the hooks can truly elevate the level of animation and interactivity in your applications. With this React Spring tutorial, you can integrate them into your projects and create engaging user experiences that will set your apps apart from the rest.

With the ability to effortlessly manipulate animations and transitions, React Spring opens up a world of creative possibilities for developers. So, take the time to explore and experiment with these hooks, and watch as your React apps come to life with stunning animations that captivate users and enhance overall user engagement.

Does your project require an application with smooth animations? Contact us to build a product with captivating visuals.

Written by Julia Shikanova and Kate Shokurova

* * *

This React Spring tutorial was originally published in March 2019 and was updated in June 2024 to make it more relevant and comprehensive.

  • Link copied!
alt

Subscribe to our blog

Once a month we will send you blog updates