# @gsap/react for using GSAP in React [](https://gsap.com/resources/React) GSAP itself is **completely framework-agnostic** and can be used in any JS framework without any special wrappers or dependencies. This hook solves a few **React-specific** friction points so that you can just focus on the fun stuff. 🤘🏻 ## `useGSAP()` A drop-in replacement for `useEffect()` or `useLayoutEffect()` that automatically handles cleanup using `gsap.context()` ### ❌ OLD (without useGSAP() hook) ```javascript import { useEffect, useLayoutEffect, useRef } from "react"; import gsap from "gsap"; // for server-side rendering apps, useEffect() must be used instead of useLayoutEffect() const useIsomorphicLayoutEffect = (typeof window !== "undefined") ? useLayoutEffect : useEffect; const container = useRef(); useIsomorphicLayoutEffect(() => { const ctx = gsap.context(() => { // gsap code here... }, container); // <-- scope for selector text return () => ctx.revert(); // <-- cleanup }, []); // <-- empty dependency Array so it doesn't get called on every render ``` ### ✅ NEW ```javascript import { useRef } from "react"; import gsap from "gsap"; import { useGSAP } from "@gsap/react"; gsap.registerPlugin(useGSAP); // register any plugins, including the useGSAP hook const container = useRef(); useGSAP(() => { // gsap code here... }, { scope: container }); // <-- scope is for selector text (optional) ``` ### ...or with a dependency Array and scope: ```javascript useGSAP(() => { // gsap code here... }, { dependencies: [endX], scope: container}); // config object offers maximum flexibility ``` If you prefer the method signature of `useEffect()` and you don't need to define a scope, this works too but the `config` object syntax is preferred because it offers more flexibility and readability: ```javascript useGSAP(() => { // gsap code here... }, [endX]); // works, but less flexible than the config object ``` So you can use **any** of these method signatures: ```javascript // config object for defining things like scope, dependencies, and revertOnUpdate (most flexible) useGSAP(func, config); // exactly like useEffect() useGSAP(func); useGSAP(func, dependencies); // primarily for event handlers and other external uses (read about contextSafe() below) const { context, contextSafe } = useGSAP(config); ``` If you define `dependencies`, the GSAP-related objects (animations, ScrollTriggers, etc.) will only get reverted when the hook gets torn down but if you want them to get reverted **every time the hook updates** (when any dependency changes), you can set `revertOnUpdate: true` in the `config` object. ```javascript useGSAP(() => { // gsap code here... }, { dependencies: [endX], scope: container, revertOnUpdate: true }); ``` ## Benefits - Automatically handles cleanup using `gsap.context()` - Implements `useIsomorphicLayoutEffect()` technique, preferring React's `useLayoutEffect()` but falling back to `useEffect()` if `window` isn't defined, making it safe to use in server-side rendering environments. - You may optionally define a `scope` for selector text, making it safer/easier to write code that doesn't require you to create a `useRef()` for each and every element you want to animate. - Defaults to using an empty dependency Array in its simplest form, like `useGSAP(() => {...})` because so many developers forget to include that empty dependency Array on React's `useLayoutEffect(() => {...}, [])` which resulted in the code being executed on every component render. - Exposes convenient references to the `context` instance and the `contextSafe()` function as method parameters as well as object properties that get returned by the `useGSAP()` hook, so it's easier to set up standard React event handlers. ## Install ```bash npm install @gsap/react ``` At the top of your code right below your imports, it's usually a good idea to register `useGSAP` as a plugin: ```javascript gsap.registerPlugin(useGSAP); ``` ## Using callbacks or event listeners? Use `contextSafe()` and clean up! A function is considered "context-safe" if it is properly scoped to a `gsap.context()` so that any GSAP-related objects created **while that function executes** are recorded by that `Context` and use its `scope` for selector text. When that `Context` gets reverted (like when the hook gets torn down or re-synchronizes), so will all of those GSAP-related objects. Cleanup is important in React and `Context` makes it simple. Otherwise, you'd need to manually keep track of all your animations and `revert()` them when necessary, like when the entire component gets unmounted/remounted. `Context` does that work for you. The main `useGSAP(() => {...})` function is automatically context-safe of course. But if you're creating functions that get called **AFTER** the main `useGSAP()` function executes (like click event handlers, something in a `setTimeout()`, or anything delayed), you need a way to make those functions context-safe. Think of it like telling the `Context` when to hit the "record" button for any GSAP-related objects. **Solution**: wrap those functions in the provided `contextSafe()` to associates them with the `Context`. `contextSafe()` accepts a function and returns a new context-safe version of that function. There are two ways to access the `contextSafe()` function: #### 1) Using the returned object property (for outside `useGSAP()` function) ```JSX const container = useRef(); const { contextSafe } = useGSAP({scope: container}); // we can just pass in a config object as the 1st parameter to make scoping simple // ❌ DANGER! Not wrapped in contextSafe() so GSAP-related objects created inside this function won't be bound to the context for automatic cleanup when it's reverted. Selector text isn't scoped to the container either. const onClickBad = () => { gsap.to(".bad", {y: 100}); }; // ✅ wrapped in contextSafe() so GSAP-related objects here will be bound to the context and automatically cleaned up when the context gets reverted, plus selector text is scoped properly to the container. const onClickGood = contextSafe(() => { gsap.to(".good", {rotation: 180}); }); return (