DEV Community

Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

5 React Motion use cases with examples

Photo by Dairui Chen on Unsplash

React-motion is a library that makes it easy to create realistic animations within components using the laws of physics. An endless possibilities of realistic animations can be explored by simply specifying values for stiffness and dampness within one of the exported components.

At first, these terms might not make so much sense to a person who’s just learning about this library, but at the end of this article, we will have discussed the meaning of these terms and looked at several use-cases where this library will prove applicable.

Prerequisites

To follow along with the flow of this article, it is necessary that you have these tools installed on your computer:

  1. Node and npm
  2. Create-react-app (npm install -g create-react-app)

We will be showing all the use cases using the create-react-app tool.

Since this article focuses on showing how to use the react-motion library in React projects, it is assumed that the reader has at least a basic knowledge of React and a general understanding of JavaScript.

By the end of this article, we will have created several simple animation projects including this animated jumbotron revealer:

A brief overview

Before we start writing code and exploring any use cases, it is imperative that we first discuss some of the basic properties of the react-motion library, so we understand it to a significant extent.

React motion exports three main components: Motion, StaggeredMotion, and TransitionMotion.

Throughout this article, we will be working with the Motion component and we will see how to import it into our development environment and design creative animations. The kind of animations we will be making are called spring animations because they start at a defined value and spring towards the destination value.

Besides the start and finish values we just discussed, there are two other values we will set when creating animations. These values (variables) are: stiffness and damping. When starting out with creating these animations, it might not be visible what impact changing these values bring about, but these variables control the overall feel and structure of each animation.

That being said, let’s briefly define them below:

Stiffness defines how forcefully the object in an animation is pulled towards its final value.

Damping is the simulated friction the object will be subject to as it approaches its target.

Tweaking these values can bring about an overwhelming or subtle change to the entire animation.

Now that we have defined these terms, we can proceed to building a few projects to demonstrate relatable use cases.

1. Hamburger menu

The first project we will be integrating react-motion into is a hamburger menu. This project isn’t difficult to build at all and can be built without writing a single line of JavaScript code.

However, this tutorial aims at demonstrating how components can easily be animated in React.

Let’s begin by creating a new project using the create-react-app tool:

create-react-app react-motion-hamburger-menu

Now let’s navigate into the newly created directory and pull in the dependencies we need:

cd react-motion-hamburger-menu

npm install --save react-motion styled-components

We are installing react-motion because we need it to animate the movement of the side section that swings into the screen when the drawer is clicked upon.

We need styled`-`components to create styled components within our application. Another perk with creating a styled component is that we are able to easily use props values from that component while styling, this already creates infinite possibilities in animation since we can dynamically use the values of props to update the style of that component.

Let’s update the App.js file, we will import the styled components package and use it to create a Wrapper component. Lastly, we will render the wrapper component and a hamburger component that we are yet to define:

https://medium.com/media/971138c6cb5bf9c1227943a6923b83b5/href

Neatly done! Now let’s create a Hamburger.js file in the src directory:

https://medium.com/media/82c3d46e08db6f70036af15c3c791649/href

In the Hamburger.js file, let’s start laying out the general structure, we will start by importing the styled-components and react-motion packages. We also want to create two components using the styled components package. These components are Drawer and Links, the former will be the drawer section that slides into the focal region of the screen when we click the hamburger icon, while the latter will hold the links on the drawer:

https://medium.com/media/0c4b85f26b8fd0872335ccbae0f5018a/href

You might have noticed that we wrote ${(props) *=>* props*.*left}vh while writing the styles for the Drawer component, we did this so that the value of the left property can be dynamic and updated as it updates in the component.

Now we can move further to defining and exporting the Hamburger component. Within the hamburger component, we want to register a constructor and call the super() function. We also register a single state toggleState which we will use to keep track of the state of the hamburger menu at any time. We will also include a method to handle the clicks on the hamburger icon.

https://medium.com/media/15776b2031ea7ded3b83f40f5af08a70/href

Now in the render function, we will write some JSX code to define the structure of the application on the DOM. For the best part, we will register a Motion component from the react motion library. The motion component adopts the render prop pattern so it accepts some props and a function as its children and we pass in our Drawer component to that function:

https://medium.com/media/e70f4bf4e17fb6e4bd50281620190382/href

It can be observed from the code above that in the motion component, we set an optional defaultStyle to *left*: -40 and then we set the style to this long expression: *left*: spring(*this.*state*.*toggleState ? 0 : -40, {*stiffness*: 210, *damping*: 10} )

These two expressions mean:

By default, set the left property (that automatically updates within the styled component) of this component to -40vh.

If the toggleState variable is set, then animate the component from its current left value (-40vh) to one of 0vh while applying a stiffness of 210 and a damping of 10. However, when it isn’t set, let it continue being equals to -40 (hence no animation)

We can run this application now to see just what we’ve built but we might be startled by its hideousness! Let’s add some CSS to the App.css file to give it a nice look:

https://medium.com/media/280ba5178992d939d88b0cfa7f5b3831/href

Awesome stuff! We can run the application now by typing this command in the root directory of the project:


npm start
``

We will point our browser to http://localhost:3000 and get this screen:

The source code for this project is available here on GitHub.

2. Preloader

Under this section, we will simulate the spinning of a preloader when some other action is running and needs time to complete before the user can get output. However, this is just a simulation so we wouldn’t tie the spinner to any larger application or process. We begin.

We can create a new application with this command:


create-react-app react-motion-preloader
``

Let’s navigate into the working directory and install dependencies using these commands:

`
cd react-motion-preloader

npm install --save react-motion styled-components bootstrap
`

We will be using styled-components in all of our projects because it makes everything easier.

Now we want to update the App.js file, we will import the styled components package and use it to create a Wrapper component. Lastly, we will render the Wrapper component and a Preloader component that we are yet to define:

https://medium.com/media/32126485bb806412e8598bff34e4e25a/href

We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js file and include this line to the list of imports *import* '*../node_modules/bootstrap/dist/css/bootstrap.min.css*' so it looks like this:

https://medium.com/media/9db83efc06ea946fff9ec5b4f00192ed/href

We will create the Preloader.js file in the src directory:

`
cd src

touch Preloader.js
`

In the Preloader.js file, let’s start laying out the general structure, we will start by importing the styled-components and react-motion packages. We also want to create a component — Loader — using the styled components package.

This components will be the actual loader/spinner:

https://medium.com/media/0d2b797026eae84f0bf832e6bd6711d0/href

We wrote ${(props) *=>* props*.*transform}deg while writing the styles for the Loader component, we did this so that the value of the transform property can be dynamic and updated as it updates in the component itself.

Now we can move further to defining and exporting the Preloader component. Within the Preloader component, we want to register a constructor and call the super() function. We also register a two state variables:

  1. startLoader
  2. numberOfSpins

The application will use the startLoader in deciding when to start the Loader, while the numberOfSpins determines how many full circles the spinner does, for this project, we will set it to 5 by multiplying 360 by 5. Lastly we will include a simple function to switch the value of startLoader from 0 to 1 to indicate that it should start the spinner on the click of a button:

https://medium.com/media/63866f7203608fbbd8ba00266fba0300/href

Now in the render function, we will write some JSX code to define the structure of the application on the DOM. We will register a Motion component from the react-motion library. The Motion accepts some props and a function as its children and we pass in the Loader component to that function:

https://medium.com/media/66feb2de26592fbd1e2e7ac8fad602de/href

The magic of this application lies in the section where we set an optimal defaultStle to *transform*: 0 and then set style to *transform*: spring(*this.*state*.*startLoader ? *this.*state*.*numberOfSpins: 0, {*stiffness*: 10, *damping*: 10}).

In very basic terms, what these mean are:

set the default property of the transform property (that is bound to the Loader component) to 0

Whenever the startLoader state variable is set, do a transform to the set number of spins.

Before we run this application, we need to include some styles in the App.css file:

https://medium.com/media/ac5e13dabc2ae4d1414221a633c90fba/href

We can run the application now by typing this command in the root directory of the project:


npm start
``

We will point our browser to http://localhost:3000 and get this screen:

Note: The spinner spins this way because we have set the stiffness and dampness to 10, you can tweak the animation to your taste by understanding the behavior of the stiffness and dampness properties from the earlier discussion and updating them adequately.

The source code for this project is available here on GitHub.

3. Progress bar

There’s hardly a person who has been on a mobile smart-phone or computer that would say he/she hasn’t seen a progress bar before. Progress bars are very important because they can communicate the status of a process to a user by showing the current length of the progress against the full-length of the bar.

Let’s build our own simple progress bar using react motion:


create-react-app react-motion-progress-bar
``

Let’s navigate into the working directory and install dependencies using these commands:

`
cd react-motion-progress-bar

npm install --save react-motion styled-components bootstrap
`

Now we want to update the App.js file, we will import the styled components package and use it to create a Wrapper component. Lastly, we will render the wrapper component and a Progresscomponent that we are yet to define:

https://medium.com/media/a023f4bd115eb19d66b030c406afdc32/href

We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js file and include this line to the list of imports so it looks like this:

https://medium.com/media/1f29da8acae4c344642a2245f34f1418/href

We will go further and create the Progress.js file in the src directory:

`
cd src

touch Progress.js
`

In the Progress.js file, we will start by importing the styled-components and react motion packages. We also want to create a component — ProgressBar — using the styled components package.

This component will be the actual ProgressBar, we will start the progress bar based on the state of a startProgress state variable. We’d also set the stiffness and damping of the motion component to 10:

https://medium.com/media/487da5125c747a9f4c529b4a399e4a3c/href

We used the Math.trunc function here to return the springed width as an integer by removing the fractional digits.

Before we run this application, let’s add these styles to the App.css file:

https://medium.com/media/9477a4420b2e1da6c813d4c07d523bc2/href

We can run the application now by typing this command in the root directory of the project:

https://medium.com/media/7e97fa8f9f7664b27dc8cdf0cf2df86f/href

We will point our browser to http://localhost:3000 and get this screen:

The source code for this project is available here on GitHub.

4. Animated notification

What’s better than being notified about the last interaction between a user and an application? You guessed it right! Being notified with a sliding animated notification in real-time. We will build a small login system that takes in a username and password then notifies the user on the status of his validation when he clicks on the Sign in button.


create-react-app react-motion-login-notification
``

Let’s navigate into the working directory and install dependencies using these commands:

`
cd react-motion-login-notification

npm install --save react-motion styled-components bootstrap
`

Now we want to update the App.js file, we will import the styled components package and use it to create a Wrapper component. Lastly, we will render the Wrapper component and a Form component that we are yet to define:

https://medium.com/media/f2838a2d8bc68097ca1d0511bf7e0397/href

We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js file and include this line to the list of imports *import* '*../node_modules/bootstrap/dist/css/bootstrap.min.css*' so it looks like this:

https://medium.com/media/09638af864af2a9daf07d8159a7828cd/href

Now let’s create a Form.js file in the src directory:

`
cd src

touch Form.js
`

In the Form.js file, we will start by importing the styled-components and react motion packages. We will define a single component using styled component, this component would be called NotificationBox. We will register a state — startAnimation — that will decide when the animation starts and we will register two functions:

  1. handleClick — This function will handle click events on the ‘sign up’ button and call the other function so it resets the state of startAnimation to 1
  2. resetValue — This function will reset the state of the startAnimation variable. https://medium.com/media/3948a2feff8f984cd0af38ae5a6f04c7/href

Within the render function, we write some JSX code that defines the structure of the form then we register a Motion component to animate the NotificationBox component:

https://medium.com/media/aef7dfa52781c3ea39c691ac8de4066b/href

As before, we have bound top and opacity properties of the component with it’s style so we get nice animations when the submit button is clicked. Let’s add the styles to the App.css file:

https://medium.com/media/0d30a3d7a94a6757750bef6203e0f862/href

We can run the application now by typing this command in the root directory of the project:

https://gist.github.com/9c977d4cc2b076ceba7f0dabd29d50e7

We will point our browser to http://localhost:3000 and get this screen:

The source code for this project is available here on GitHub.

5. Animated Jumbotron revealer

We’ve looked at some basic examples so far, but now we’d look at something more complex, we are going to create an animated “jumbotron revealer.” In simpler terms, this is an application that displays a black screen on initial load then gradually reveals the jumbotron using react motion. Let’s get started.

We will create a new project:


create-react-app react-motion-jumbotron-revealer
``

We can navigate into this directory and install the dependencies:

`
cd react-motion-jumbotron-revealer

npm install --save react-motion styled-components
`

Let’s make a quick edit to the App.js file, we want to import styled-components and also import ImageBoxAnimation (which is a component we’d create very soon):

https://medium.com/media/3a8676b4dc90ce9148954a7d2c64c8e0/href

We need to create two separate files for two components so let’s navigate into the src directory and create them:

`
cd src

touch ImageBoxAnimated.js

touch BlackBoxAnimated.js
`

Awesome! Now let’s open up the ImageBoxAnimated.js file in our favorite editor and begin writing some code, the first thing we want to do is import the dependencies and the BlackBoxAnimated component (though the file is currently empty) then create a new component using the styled components. The ImageBox component will basically be a div that loads a picture as its background image from the internet:

https://medium.com/media/517058cf8f4f25ad8ac7efef69292301/href

The next thing we will do is create the ImageBoxAnimation component and set a single state variable — animationNumber — we need this state variable to decide when the black boxes that will initially cover the jumbotron will start to slide away.

We will also define a function — startNextAnimation — which serves the purpose of augmenting the animationNumber that decides which box slides.

We will use the setTimeout() function to call the startNextAnimation function that increments the animationNumber. Whenever a timeout runs, a new black box will slide (there will be about 10 of them by the completion of this project) across the jumbotron’s image.

In the render function, we will start by initializing an object { animationNumber } to our application’s current state so that we can refer to it directly within the render function without having to call this.

Next, we will register 10 instances of the BlackBoxAnimated component and pass down three props to each one of them, these props are:

heightPercentage — This props is responsible for setting the height of each black box relative to the total height of the jumbotron. We will set it to 10% so that we have space for exactly 10 boxes

reverseDirection — This props takes a boolean value to decide in which direction the box should slide, because if all the boxes slide in one direction, then it would be visually boring. We will alternate between truth and false to give it a zigzag feel.

startAnimation — This props is very important because it is responsible for the cascading behaviour of the animation. It makes sure that the black boxes leave one at a time (because the setTimeout function gives a space of half a second before calling the setNextAnimation function which is responsible for increasing the value of animationNumber by 1) by comparing its value against a number and returning a boolean value to the BlackBoxAnimated component. A false does nothing while a true starts the animation.

Finally, we will export the application:

https://medium.com/media/c726d72ab4bb23c6ea160823bfe876b8/href

Now that that’s done, let’s open the BlackBoxAnimated.js file we created a while ago and prepare it for the data that is being passed down by ImageBox. We will start by importing the dependencies we’ll need, but this time we will also import PropTypes *from* '*prop-types*' and this would help us confirm that our props are what we want them to be when they are being received. We will also define a Blackbox component using styled components and populate it with some styles:

https://medium.com/media/2915fa519479ef441d352ea60f78ba7c/href

We are using ${(props) *=>* props*.*heightPercentage}% and ${(props) *=>* props*.*xDirection} center because we want to bind these props from the component with the style properties.

Next, we will create the BlackBoxAnimated component (you can define a component as a function in React) and define the props it should expect. We will register the Motion component and trigger the animation only when startAnimation has the value if true.

Lastly, we will check that the props we received in the component are of the type we expected:

https://medium.com/media/2d312c7aff6bd988c7296bf5ad12c1ac/href

Great, we can run the application now by typing this command in the root directory of the project:


npm start
``

We will point our browser to http://localhost:3000 and get this screen:

The source code for this project is available here on GitHub.

Conclusion

In this article, we have seen how to use React Motion to tweak animations with React components, we have also come to understand the ideas behind the stiffness and damping variables that are available to us when using the library.

Though the examples we have looked at in this tutorial mainly covered the basic sides to the library, it’s a good start for anyone who hopes to build really complex and nice looking web animations with components.

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.


Top comments (0)