New Hook Just Dropped
Over the past few years, I've primarily relied on Framer Motion for handling my animations, while incorporating GSAP from time to time, I found it to be somewhat verbose compared to Framer, especially in a React context.
But, check this out, yesterday GSAP introduced the useGSAP()
hook, an addition to easily integrate GSAP with React.
Prior to this, animating elements involved wrapping them in a gsap.Context
object, then, you had to use the same object's methods like .revert()
or .kill()
within useEffect()
or useLayoutEffect()
's cleanup function to avoid memory leaks, depending if you're within an SSR context or not, along with a mandatory dependency array that you have to keep track of.
It's just a lot of overhead really to do something silly like
You'd need to
import React, { useRef, useEffect, useLayoutEffect } from 'react';
import gsap from 'gsap';
const useIsoLayoutEffect =
typeof window !== 'undefined' ? useLayoutEffect : useEffect;
const Component: React.FC = () => {
const container = useRef<HTMLDivElement>(null);
useIsoLayoutEffect(() => {
const ctx = gsap.context(() => {
const tl = gsap.timeline({ repeat: -1, repeatDelay: 0.5 });
tl.to('.x', {
rotation: 360,
duration: 2,
borderRadius: 16,
translateX: -150,
ease: 'power1.inOut',
});
tl.to('.x', {
rotation: -360,
duration: 2,
borderRadius: 0,
translateX: 150,
ease: 'power1.inOut',
});
tl.to('.x', {
rotation: 360,
duration: 2,
borderRadius: 16,
translateX: 0,
ease: 'power1.inOut',
});
}, container);
return () => ctx.revert();
}, []);
return (
<div>
<div
ref={container}
className="flex flex-col items-center justify-center gap-10"
>
<div className="x w-10 h-10 bg-red-400 rounded-2xl animate-pulse"></div>
<div className="x w-10 h-10 bg-yellow-400 rounded-2xl animate-pulse"></div>
<div className="x w-10 h-10 bg-green-500 rounded-2xl animate-pulse"></div>
</div>
</div>
);
};
This new hook abstracts away these inconveniences, and obviates the need for explicit cleanup. So the same logic above can be written as
useGSAP(
() => {
const tl = gsap.timeline({ repeat: -1, repeatDelay: 0.5 });
tl.to('.x', {
rotation: 360,
duration: 2,
borderRadius: 16,
translateX: -150,
ease: 'power1.inOut',
});
tl.to('.x', {
rotation: -360,
duration: 2,
borderRadius: 0,
translateX: 150,
ease: 'power1.inOut',
});
tl.to('.x', {
rotation: 360,
duration: 2,
borderRadius: 16,
translateX: 0,
ease: 'power1.inOut',
});
},
{ scope: container}
);
It looks hella cleaner IMO, I actually like this update, I mean it's not a lot but hey, it gets the job done a lot easier so, I might use even more now, and sorry if you thought this is an educational post where I teach you about GSAP, nope, I'm just glad they introduced this new hook, that's it.