Animating Your React Components

Improve overall customer experience by animating components in your React app or component library

Albin Groen
Level Up Coding
Published in
7 min readAug 1, 2020

--

Image by Carl Joseph from unsplash.com

So, you want to take your React components to the next level? Implementing animations can greatly improve the customer experience and make your app feel more professional. Animations are one of many ways to accomplish this. In this article, I want to go through how you can easily animate your React components using framer-motion.

How to get started

To set up your project to use framer-motion you can simply install it by using your JavaScript package managers like NPM or Yarn. Run any of the following commands inside of your React.js project and you will be ready to go.

$ npm install framer-motion$ yarn add framer-motion

Different types of animations

So, in framer-motion there a couple of different types of animations that you can use as tools to animate your components. Here are the ones we are going to cover in this article. You can also find much more information on the official framer-motion documentation site here.

  • Animating a single component
  • Animating component mounts and unmounts
  • Animating between component states
  • Animating multiple components

Animating a single component

So a good place to start trying out animation in React is to simply animate a single component. To do this, we will use the motion component provided by the framer-motion package. This lets us replace our default html divs with motion.div, and therefor get exposed the possibility to easily animate them. To animate a component in a x-axis, we can write the following.

import React from 'react'
import { motion }from 'framer-motion'
const MyComponent = ({ children }) => (
<motion.div animate={{ x: 500 }}>
{children}
</motion.div>
)

And by using our component like this:

import MyComponent from "../components/component";export default function App() {
return (
<MyComponent>
<h3>This will animate</h3>
</MyComponent>
);
}

The output will look like this and it will animate directly when it mounts.

A black text saying “This will animate” coming out from the left in a fast “bouncy” transition

Although this might not seem like a very useful animation, this is just the basic concept of animating a React component. Now we will use our learnings to further develop our React components to use more complex animations to animate between states and mounts. Starting off, let us animate a component between being visible and not visible.

Animating presence

Animating presence can be done in a couple of different ways. We will do this by just slightly updating our previous component, and in our parent component where we will add the AnimatePresence component provided by framer-motion to animate between mounting and unmounting from the dom. This most accurately represents how you most likely use your React components today. We will update our component to look like this:

import { motion, AnimatePresence } from "framer-motion";export default function MyComponent({ children }) {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ x: 250, opacity: 1 }}
exit={{ opacity: 0, x: 500 }}

>
{children}
</motion.div>
);
}

By adding the initial prop, updating the animate, and adding the exit prop we will ensure that the AnimatePresence component knows exactly how to animate this component when it mounts and unmounts from the dom. If we do not supply proper values the animation may not work. Now, to animate our component when it mounts and unmounts from the dom, we need to update our parent component a little bit.

import { useState } from "react";
import { AnimatePresence } from "framer-motion";
import MyComponent from "../components/component";
export default function App() {
const [isOpen, setIsOpen] = useState();
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>
Toggle component
</button>
<AnimatePresence>
{isOpen && (
<MyComponent>
<h3>This will animate</h3>
</MyComponent>
)}
</AnimatePresence>
</div>
);
}

Now, this is what our component should look like. When clicking the button the first time, the component is going to animate onto the page, and when clicking it again it is going to animate out from the page. Since we specified our initial, animate, and exit props on our component, framer-motion now knows how to animate it between its different states.

A button being clicked toggling a black text saying “This will animate” coming out from the left in a fast “bouncy” transition. When clicking the button again it continuous its transition to the right and then disappears.

Animating between component states

Now, let us say your component itself has different local states — and when it changes you want your element to animate. We can accomplish this by using the motion element together with the layout property. We will try this out by creating a fairly usual but important component — a Switch.

import { motion } from "framer-motion";export default function Switch({ isOn, onToggle }) {
const styles = {
wrapper: {
display: "flex",
justifyContent: isOn ? "flex-end" : "flex-start",
borderRadius: 50,
width: 60,
padding: 4,
},
handle: {
height: 25,
width: 25,
background: "#fff",
borderRadius: "50%",
},
};
return (
<motion.div
style={styles.wrapper}
onClick={() => onToggle(!isOn)}
animate={{ background: isOn ? "#006aff" : "#ddd" }}

>
<motion.div layout style={styles.handle} />
</motion.div>
);
}

And by using it like this in our parent component:

import { useState } from "react";
import Switch from "../components/switch";
export default function App() {
const [isOn, setIsOn] = useState();
return <Switch isOn={isOn} onToggle={() => setIsOn(!isOn)} />;
}
A switch component on a blank page that’s being animated between a on and off state by clicking on it. When in the on state the switch has a blue background, and when in the off state it has a gray background.

Animating multiple components

So, with our newly gathered knowledge on how to easily animate React components, we will now bring it all together to animate a more real world example with multiple components. Framer-motion certainly has a lot more features than we are going to cover in this article — but these examples will definitely help you kickstart your journey towards animating React components.

Example: Animating notifications

We will create a new component in our project called Notification, and from there we will start combining what we have learned to animate several notifications in a layout in a professional manner.

Here is the code for the new component. It is going to use the motion element with the initial, animate, and exit props to accomplish to the desired transition when mounting and unmounting from the dom.

We are also going to apply the layout prop to make sure AnimatePresence knows that each component should be aware of its siblings to create smooth height adjustments to the wrapper.

import { motion } from "framer-motion";export default function Notification({ title, description, onClose, id }) {
const styles = {
wrapper: {
boxShadow: "0px 5px 30px 0px rgba(0,0,0,0.1)",
borderRadius: 5,
padding: 16,
margin: "1rem 0",
},
};
return (
<motion.div
layout
initial={{ opacity: 0, x: 200 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 200 }}

style={styles.wrapper}
>
<h2>{title}</h2>
<p>{description}</p>
<button onClick={() => onClose(id)}>Close</button>
</motion.div>
);
}

And to use the component we will add this to our parent component:

import { useState } from "react";
import { AnimatePresence } from "framer-motion";
import Notification from "../components/notification";
export default function App() {
const [notifications, setNotifications] = useState([]);
const pushNotification = (notification) => {
setNotifications([...notifications, notification]);
};
const styles = {
notifications: {
top: 0,
right: 0,
position: "fixed",
},
};
return (
<div>
<button
onClick={() =>
pushNotification({
title: "Test notification",
description:
"This is a test notification that is being animated using framer-motion",
id: Math.random(),
onClose: (id) => {
setNotifications((currentNotifications) =>
currentNotifications.filter(
(notification) => notification.id !== id
)
);
},
})
}
>
Push notification
</button>
<div style={styles.notifications}>
<AnimatePresence>
{notifications.map((notification) => (
<Notification {...notification} key={notification.id} />
))}
</AnimatePresence>
</div>
</div>
);
}

Voila! We have now built a way to animate notifications coming in on the page. This greatly enhances to experience for the user, compared to the notifications just appearing and disappearing from the page without any sort of transition. Just by supplying a few props and wrapping our components in a AnimatePresence we achieved this. This is really only scratching the surface of what animation libraries like framer-motion can do.

What is next?

Depending on your position in the industry, animations might not be the most important part of your product. For example, if you are bootstrapping a startup or building a very corporate software, animating every single React component might not be a very good return on investment (ROI). But if your work on a larger company where customer experience is greatly valued, or you are building your own startup and is really focused on design, animating your components can definitely enhance the customer experience and the general feel of your app.

Animation really depends on the audience. If you are building an app for kids, then this is more or less a necessity. On the other hand — if you are building something for elderly people or for people with certain disabilities, you should consider reducing the amount of motion on your app. There are a lot of great resources on the web on how to manage this and make sure every user gets the most pleasant experience. Thank you for reading, and good luck with your journey of animating React components!

--

--

Hi! I’m Albin, a front-end developer from Sweden passionate about software development, design, and self-improvement.