budding

GreenSock Animations with React Hooks

How to use the Greensock animation library inside React using React hooks

Using the GreenSock web animation library (also known as gsap) in vanilla JavaScript isn’t too complex. But when we want it to play nicely with a frontend framework like React, we run into some finicky issues.

This guide is specifically about using React Hooks with GreenSock, as many of the existing guides only explain how to set it up with the old style of class components.

This isn’t an introduction to the GreenSock library itself – head over to my post on The Bare Essentials of Greensock for that.


React, Meet GreenSock

The issue with combining these two libraries is that React acts as a DOM interloper – it sits between the code we write and the DOM, managing it for us.

React builds it’s own internal “tree” of DOM nodes based off our code, and only updates the actual DOM as needed (a concept previously known as the React Virtual DOM ) The React team has gone off the term of the virtual DOM and prefer to talk about the render tree. Potatoes, potataos. For more on how the virtual DOM works, I have an illustrated guide

A diagram of React generating all the DOM nodes for us

Meanwhile, the GreenSock library usually works by directly animating our DOM elements. Perhaps you can sense the tension in the room…

Since the GreenSock library needs access to the DOM in order to animate it, we need to tell React about our Greensock animations. Otherwise the two end up in awkward arguments that can end in tears (primarily mine).

Bring in the React Hooks

There’s two essential React hooks we’ll use to connect our React code to our Greensock code: useRef and useEffect

useRef lets us access and directly target our DOM nodes

useEffect lets us to perform side effects – any functions or data requests that we want to run after rendering the component to the DOM

If you’re not completely comfortable with React Hooks yet and those technical explanations mean nothing to you, don’t worry we’re going to slowly walk through this. With illustrations. Because who the fork properly understands “side effects”?


Getting Setup

We first need to run yarn install gsap or npm install gsap into our React project repo gsap is short for GreenSock Animation Platform and it’s the way we reference the Greensock library in all our code sytax

Feel free to open up a Codesandbox project to work through the steps while you read. I’ve set one up for you with React and Greensock already installed:


Building our Animation Component

Let’s start by creating a React component called <AnimatedBox/> that is going to hold all our Greensock code. We’re going to build a simple <div> element and have it animate across the page (exciting!).

We’ll need to import the Greensock library into our component with import { gsap }from 'gsap', as well as React and our two hooks with import React, { useRef, useEffect } from 'react'

import React, { useRef, useEffect } from "react";
import { gsap } from "gsap";

const Animation = () => {
	return (
		<div
			style={{
				width: "160px",
				height: "160px",
				background: "salmon",
			}}
		/>
	);
};

I’ve set some basic width, height, and color CSS styles on our div to make it visible on the page.

Good looking div, right? Salmon is always the right color choice.


Adding the useRef Hook

We’re now going to add references to our animation with the useRef hook.

We create a new reference by adding const boxRef = useRef() anywhere outside of our return statement. Call it anything you like, but boxRef is a good enough name for this example.

We then add a ref={boxRef} attribute on our <div> element.

const Animation = () => {
	const boxRef = useRef();

	return (
		<div
			ref={boxRef}
			style={{
				width: "120px",
				height: "120px",
				background: "salmon",
			}}
		/>
	);
};

This tells React we want to be able to control our <div> element with the boxRef reference once our component is mounted onto the DOM.


Adding the useEffect Hook

Next we’re going to add our useEffect hook, and write our GreenSock animation inside of it.

If you’re already familiar with greensock this will look fairly straightforward.

const Animation = () => {
	const boxRef = useRef();

	useEffect(() => {
		gsap.to([boxRef.current], {
			x: "400px",
			duration: 2,
		});
	});

	return (
		<div
			ref={boxRef}
			style={{
				width: "120px",
				height: "120px",
				background: "salmon",
			}}
		/>
	);
};

We declare a normal gsap.to() tween, but instead of passing in an id or class name as the target element, we use [boxRef.current].

This means we want gsap to animate the .current property of our boxRef reference – which is the <div> element we put that reference on.

gsap.to([boxRef.current], {});

We then pass in our variables object, which tells Greensock to move our div 400px along the x axis over a duration of 2 seconds:

{ x: 400px, duration: 2 }

And thus, our div animates…

Tada 🎉

So by this point, you hopefully have a working animation in that Codesandbox project or a local repo.


If you don’t feel like mucking around with useRef and useEffect, John Lindquist created a simple React hook called use-gsap that hides them away.