The useGSAP() hook

The useGSAP() hook

Table of contents

GSAP is framework-agnostic which means it can be used in any JS framework without any special wrappers or dependencies. However, this hook solves a few React-specific pain points that are significant.

In React we can use lifecycle hooks like useEffect() or useLayoutEffect()to render animations of GSAP.

import React, { useEffect } from 'react'

export const Blogs = () => {
    useEffect(()=>{
        // gsap code here...
        console.log("Hello");
    })
    return (
        <div className="flex justify-center items-center min-h-screen">
            <div className="text-4xl"></div>
        </div>
    )
}

But React 18 runs in Strict Mode by default which causes your Effects to get called TWICE.

<StrictMode>
  <App />
</StrictMode>

If you don't revert things properly, this can lead to duplicates (as shown in the image below), conflicting animations, or logic issues from tweens.

Thus, with useEffect() we have to unsubscribe from every animation we apply inside to revert the changes manually in the next render for a smooth UX.

Another reason why useEffect() shouldn't be used to fetch APIs anymore :(

useGSAP() is a direct stand-in for useEffect()or useLayoutEffect() that automatically handles cleanup using 'contextSafe'. Import the useGSAP() hook from @gsap/react and you're good to go!

import { useGSAP } from '@gsap/react'
import gsap from 'gsap';

export const Flipping = () => {
// ................
// using useGSAP hook within a safe context for automatic cleanup after render
    const { contextSafe } = useGSAP(()=>{
        //  gsap code here...
    },{scope: container}); 
//useGSAP hook is the gsap equivalent of the useEffect hook for animations

// an animation method written with safe context
    const animateState = contextSafe(() => {
        //  gsap code here...
    })
     return (
         <div onClick={animateState}>
         <div/>
    )
}

Here, we can also observe another property of useGSAP():

The config Object

This second property is optional. You can pass either a dependency array-like useEffect()-object for more flexibility. This offers a range of options as shown below:

// config object offers maximum flexibility
useGSAP(() => {
  // gsap code here...
}, { dependencies: [endX], scope: container, revertOnUpdate: true}); 
// scope refers to the DOM object limit for the animations to occur

useGSAP(() => {
  // gsap code here...
}, [endX]); // simple dependency array setup like useEffect, 
// good for state-reactive animation

useGSAP(() => {
  // gsap code here...
}); // defaults to an empty dependency array '[]' and no scoping.

Therefore, all GSAP animations, ScrollTriggers, Draggables, and SplitText instances created when the useGSAP() hook executes will be reverted automatically when the component unmounts and the hook is torn down.

These animations are considered 'context-safe'.

However, if you create any animations that get called after the useGSAP() hook executes (like click event handlers, something in a setTimeout(), or anything delayed), those animations will not be context-safe.