npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill gsap-reactSKILL.md
GSAP React Integration
React-specific patterns for GSAP animations.
Quick Start
npm install gsap @gsap/react
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
function Component() {
const containerRef = useRef(null);
useGSAP(() => {
gsap.to('.box', { x: 200, duration: 1 });
}, { scope: containerRef });
return (
<div ref={containerRef}>
<div className="box">Animated</div>
</div>
);
}
useGSAP Hook
Basic Usage
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
function AnimatedComponent() {
const container = useRef(null);
useGSAP(() => {
// All GSAP animations here
gsap.from('.item', {
opacity: 0,
y: 50,
stagger: 0.1
});
}, { scope: container }); // Scope limits selector queries
return (
<div ref={container}>
<div className="item">Item 1</div>
<div className="item">Item 2</div>
<div className="item">Item 3</div>
</div>
);
}
With Dependencies
function AnimatedComponent({ isOpen }) {
const container = useRef(null);
useGSAP(() => {
gsap.to('.drawer', {
height: isOpen ? 'auto' : 0,
duration: 0.3
});
}, { scope: container, dependencies: [isOpen] });
return (
<div ref={container}>
<div className="drawer">Content</div>
</div>
);
}
Returning Context
function Component() {
const container = useRef(null);
const { context, contextSafe } = useGSAP(() => {
gsap.to('.box', { x: 200 });
}, { scope: container });
// Use contextSafe for event handlers
const handleClick = contextSafe(() => {
gsap.to('.box', { rotation: 360 });
});
return (
<div ref={container}>
<div className="box" onClick={handleClick}>Click me</div>
</div>
);
}
Ref Patterns
Single Element Ref
function SingleElement() {
const boxRef = useRef(null);
useGSAP(() => {
gsap.to(boxRef.current, {
x: 200,
rotation: 360,
duration: 1
});
});
return <div ref={boxRef}>Box</div>;
}
Multiple Element Refs
function MultipleElements() {
const itemsRef = useRef([]);
useGSAP(() => {
gsap.from(itemsRef.current, {
opacity: 0,
y: 30,
stagger: 0.1
});
});
return (
<div>
{[1, 2, 3].map((item, i) => (
<div
key={item}
ref={el => itemsRef.current[i] = el}
>
Item {item}
</div>
))}
</div>
);
}
Dynamic Refs
function DynamicList({ items }) {
const itemsRef = useRef(new Map());
useGSAP(() => {
gsap.from(Array.from(itemsRef.current.values()), {
opacity: 0,
y: 20,
stagger: 0.05
});
}, { dependencies: [items.length] });
return (
<div>
{items.map(item => (
<div
key={item.id}
ref={el => {
if (el) itemsRef.current.set(item.id, el);
else itemsRef.current.delete(item.id);
}}
>
{item.name}
</div>
))}
</div>
);
}
Context and Cleanup
Automatic Cleanup
// useGSAP automatically cleans up animations on unmount
function Component() {
useGSAP(() => {
// This timeline is automatically killed on unmount
gsap.timeline()
.to('.a', { x: 100 })
.to('.b', { x: 100 });
});
}
Manual Context (Without useGSAP)
import gsap from 'gsap';
function Component() {
useEffect(() => {
const ctx = gsap.context(() => {
gsap.to('.box', { x: 200 });
gsap.to('.circle', { rotation: 360 });
});
return () => ctx.revert(); // Cleanup
}, []);
}
Scoped Context
function Component() {
const containerRef = useRef(null);
useEffect(() => {
const ctx = gsap.context(() => {
// Selectors only query within containerRef
gsap.to('.item', { opacity: 1 });
}, containerRef);
return () => ctx.revert();
}, []);
}
Event Handlers
contextSafe for Events
function InteractiveComponent() {
const container = useRef(null);
const { contextSafe } = useGSAP(() => {
// Initial animation
gsap.set('.box', { scale: 1 });
}, { scope: container });
const handleMouseEnter = contextSafe(() => {
gsap.to('.box', { scale: 1.1, duration: 0.2 });
});
const handleMouseLeave = contextSafe(() => {
gsap.to('.box', { scale: 1, duration: 0.2 });
});
return (
<div ref={container}>
<div
className="box"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
Hover me
</div>
</div>
);
}
useCallback Alternative
function Component() {
const boxRef = useRef(null);
const tweenRef = useRef(null);
const animateBox = useCallback(() => {
tweenRef.current?.kill();
tweenRef.current = gsap.to(boxRef.current, {
x: '+=50',
duration: 0.3
});
}, []);
use
...
Repository Stats
Stars4
Forks0