Creating Reusable Animation Components with React and GSAP

Nathan Sebhastian
Bits and Pieces
Published in
9 min readJan 20, 2021

--

GSAP or GreenSock Animation Platform is a JavaScript animation library that helps you to create fast and silky smooth animations for your interface. It provides simple APIs that grants you full control over your animation sequences, but easy enough to understand and use for simple animations

This tutorial will show you two things:

  • How to use GSAP in React for simple animations
  • How to create reusable animation components with React and GSAP. These components will then be exported to Bit’s virtual monorepo, to make them available to other web projects.

If you’re already familiar with GSAP, you can skip ahead to part two.

Part One: Understanding GSAP animation APIs

Let’s learn how you can use GSAP to animate JSX elements. The knowledge you will learn in this tutorial will help you to build a reusable animation component later.

GSAP is basically a property manipulator machine that will update your DOM elements’ positions many times per second, giving an illusion of moving texts and objects on your web page interface. It needs you to pass the reference of the element you want to animate to GSAP’s animation API.

For example, let’s say you want to animate an <h1> element. You can get the reference for the element by using document.getElementById:

const myHeader = document.getElementById("header-h1");gsap.to(myHeader, {
opacity: 0,
duration: 2,
});

Let’s focus on implementing the code above in React first. I will explain the gsap.to() method later.

To reference an element in React, you can use the useRef hook to get the reference to the element. You can then use the reference in a useEffect hook to ensure that the animation is called right after the element is rendered on the screen.

Here’s an example:

import { useEffect, useRef } from "react";function App() {
const myHeader = useRef(null);

useEffect(() => {
// call the animation method here
}, []);
return (
<h1 ref={myHeader}>Hello World</h1>
);
}

All you need now is to call the animation method. There are three GSAP methods available for creating simple animations:

  • gsap.to()
  • gsap.from()
  • gsap.fromTo()

The to() method will change your element’s property to certain values that you defined. For example, you can animate an element’s opacity to zero over two seconds like this:

import React, { useEffect, useRef } from "react";
import { gsap } from "gsap";
function App() {
const myHeader = useRef(null);
useEffect(() => {
gsap.to(myHeader.current, {
opacity: 0,
duration: 2,
});

}, []);
return <h1 ref={myHeader}>Using gsap.to() method</h1>;
}

Here’s the to() method example:

The from() method is simply the opposite of to() method. When you write from opacity zero, your element will animate from invisible to visible:

function App() {
const myHeader = useRef(null);
useEffect(() => {
gsap.from(myHeader.current, {
opacity: 0,
duration: 2,
});

}, []);
return <h1 ref={myHeader}>Hello World</h1>;
}

Finally, you can use the fromTo() method to define both the starting and ending point of the animation. This method is like a combination of both from() and to() methods:

import React, { useEffect, useRef } from "react";
import { gsap } from "gsap";
function App() {
const myHeader = useRef(null);
useEffect(() => {
gsap.fromTo(
myHeader.current,
{ opacity: 0 },
{ opacity: 1, y: -70, duration: 3 }
);

}, []);
return <h1 ref={myHeader}>Using gsap.fromTo() method</h1>;
}

Now that you know how to animate React components with GSAP, let’s look at how you can write a reusable animation component next.

Part Two: Creating reusable animation component with React and GSAP

This second part will help you to develop a reusable React animation component that can be shared across different projects and repositories by using the Bit platform.

Bit is a component collaboration platform that enables you to share components between different projects and repositories. It’s a very handy tool that handles registering, testing, updating, and installing your components.

Bit.dev in action

We’ll be using Bit in combination with Bit’s cloud service — Bit.dev (which is also free, for most uses). You may also choose to use your own server, instead.

We’ll create a reusable animation component with React and GSAP, that accepts animation parameters as props. For example, let’s say you want to create a reusable animation component that “fades” into the screen (known as fade-in animation)

Our React animation component will receive the following props:

  • children — the component that you want to animate
  • direction — the direction of your animation. Your component won’t move if not defined
  • duration — how long the animation will end, the smaller the number, the faster.
  • distance — where the component will start to appear. Will move in the direction you specified

We’ll also handle the fade direction. You can animate your component up, down, left, or right by using the switch statement as follows:

const FadeIn = ({
children,
direction,
duration,
distance,
}) => {
let componentRef = useRef(null);
let fadeDirection;
switch (direction) {
case "left":
fadeDirection = { x: distance };
break;
case "right":
fadeDirection = { x: -distance };
break;
case "up":
fadeDirection = { y: distance };
break;
case "down":
fadeDirection = { y: -distance };
break;
default:
fadeDirection = { x: 0 };
}
return <div ref={componentRef}>{children}</div>;
};

Once you have the fade direction, all you need is to initiate the animation using theuseEffect hook:

const FadeIn = ({
children,
direction = null,
duration = 1,
distance = 200,
}) => {
let componentRef = useRef(null);
let fadeDirection;
switch (direction) {
case "left":
fadeDirection = { x: distance };
break;
case "right":
fadeDirection = { x: -distance };
break;
case "up":
fadeDirection = { y: distance };
break;
case "down":
fadeDirection = { y: -distance };
break;
default:
fadeDirection = { x: 0 };
}
useEffect(() => {
gsap.from(componentRef.current, {
duration,
opacity: 0,
...fadeDirection,
});
}, [duration, fadeDirection]);
return <div ref={componentRef}>{children}</div>;
};

Since we’re going to share our components with others, documenting and type-checking it is mandatory.

FadeIn.propTypes = {
/**
* The component to animate
*/
children: PropTypes.node.isRequired,
/**
* The direction of the animation
*/
direction: PropTypes.string,
/**
* The duration over which the animation will be done (in seconds)
*/
duration: PropTypes.number,
/**
* The distance where the animated component will move in pixels
*/
distance: PropTypes.number,
};
FadeIn.defaultProps = {
direction : null,
duration : 1,
distance : 200,
};

The values above will also be used by Bit to auto-generate short documentation, which I will show you later.

And now your FadeIn animation component is ready. You can import the component and test the animation by passing a simple <h1> component. Pass the direction as a prop as well to see if it works:

import FadeIn from "./FadeIn";function App() {
return (
<FadeIn direction="left">
<h1> Hello World!</h1>
</FadeIn>

);
}
export default App;

Congratulations! You’ve just learned how to create a reusable animation component with GSAP and React. For the next step, why don’t you try to create your own reusable animation component using the above example as a reference?

my fade-in React animation component shared on Bit.dev

Registering your component to Bit’s registry

You need to create a free account with Bit here to start using its platform. After you’ve registered, create a new collection where you will save your components. You can name your collection anything, but I will name mine gsap-react :

Creating a new collection

Each Bit user can have many collections, and a collection can have many components. You can set your collection to either private or public. Once your collection is created, you’re ready to publish your components to Bit.

Please note that we are not only publishing packages but independent components that are source-controlled, published, and installed, independently.

Publishing your component to Bit

To share your component on Bit, first, open your terminal and install the Bit terminal tool:

npm install bit-bin --global

Once installed, head back to your React project’s terminal and initialize a new Bit workspace:

bit init

This command will create the following resource for you:

  • Bit workspace configuration inside package.json
  • Components bitmap with .bitmap file

In your package.json file, you’ll see a new bit config similar to this:

"bit": {
"componentsDefaultDirectory": "components/{name}",
"packageManager": "npm"
}

Next, you need to login into your Bit account from the terminal:

bit login

The command above will open a new window where you can log in to your Bit account. Once logged in, you’re ready to publish your components.

To start the publishing process, add your components using the bit add command:

bit add src/components/*

You can review components you’ve tracked on Bit, but please don’t publish them just yet:

bit status

Before you publish the components, you need to make sure that these components are consumable by other projects and have no errors. You can do that by building these components using Bit compiler for React:

bit import bit.envs/compilers/react --compiler
bit build

Bit React compiler will build your components in an isolated environment to make sure the build will also succeed on the cloud or in any other repository. For other compilers, see here.

Once the build is done and you have no error, you can tag your components as ready to publish. For example:

bit tag fade-in 0.0.1

A different way would be to tag them all, whether with a version number or without (in which case, Bit will increase the patch number of each component).

bit tag --all

As you continue to develop your application, you can update a component that you’ve tagged previously by incrementing its version number:

bit tag fade-in 0.0.2

Alright, now that we have the components tagged, let’s publish them to a Bit collection by using the bit export command and the full name of the collection structured as <username>.<collection>:

bit export nsebhastian.gsap-react

Once done, you can visit the bit.dev website and see your components published inside the collection.

If you click on one of the components, you’ll see that Bit also has a playground that renders the component, so you can see it in action without needing to download it first. You’ve seen this playground from the screenshots earlier:

The Fade In animation component we created earlier

And just below the playground, you’ll find the documentation of the properties available for this component:

Component documentation generated by Bit

With that, you’re now ready to reuse the component in other projects. You can reuse this component in other projects. Whenever you need to use the component, you can simply install it with npm or yarn:

npm i @bit/nsebhastian.gsap-react.fade-in# oryarn add @bit/nsebhastian.gsap-react.fade-in

Your team members can also use Bit to import the component’s source code and make some contribution to it:

bit import nsebhastian.gsap-react/fade-in

The “imported” component source code is cloned into the current terminal’s working directory. Your team members (or anyone else if the collection is public) can change the code, tag it with a new version, and “push” it back to the collection.

If you want to learn more about Bit, I have written tutorials on how to share components between Next.js projects, or even between React and React-Electron.

Conclusion

GSAP is one of the best JavaScript animation libraries available for web developers today that’s very easy to use for simple animations, yet still powerful enough to do complex animations. If you want to learn more about GSAP, don’t forget to check out its documentation.

By combining React and GSAP, you can create a reusable animation component, which you can then share to Bit. Components shared with Bit are independently source-controlled and packaged, allowing you to reuse them in other projects easily.

Learn More

--

--

Web Developer and Writer. Sharing what I learn on productivity and success.