gsap-react
v1.3.2
Published
Collection of React utilities and hooks for GSAP
Downloads
340
Maintainers
Readme
GSAP React
Collection of React utilities and hooks for GSAP.
Installation
- Requires gsap version 3.11.0 or newer
npm
npm install gsap-react gsap
yarn
yarn add gsap-react gsap
pnpm
pnpm add gsap-react gsap
Hooks
useGsapContext
Memoises a GSAP Context instance.
Usage:
import { useGsapContext } from 'gsap-react'
import { useLayoutEffect, useRef } from 'react'
function App() {
const ref = useRef<HTMLDivElement>(null)
const ctx = useGsapContext(ref)
useLayoutEffect(() => {
ctx.add(() => {
gsap.to('.box', {
x: 200,
stagger: 0.1,
})
})
return () => ctx.revert()
}, [])
return (
<div className="app" ref={ref}>
<div className="box">Box 1</div>
<div className="box">Box 2</div>
<div className="box">Box 3</div>
</div>
)
}
useGsapEffect
Use register effect.
Usage:
import { useGsapEffect } from 'gsap-react'
import { useRef } from 'react'
function App() {
const box = useRef()
const animation = useGsapEffect(box, 'spin')
return <Box ref={box}>Hello</Box>
}
useSelector
Query selector
Usage:
import { gsap } from 'gsap'
import { useSelector } from 'gsap-react'
import { useLayoutEffect } from 'react'
function App() {
const [q, ref] = useSelector<HTMLDivElement>(null)
useLayoutEffect(() => {
gsap.to(q('.box'), { x: 200 })
}, [])
return (
<div ref={ref}>
<div className="box">Box 1</div>
</div>
)
}
useStateRef
This hook helps solve the problem of accessing stale values in your callbacks. It works exactly like useState, but returns a third value, a ref with the current state.
Usage:
const [count, setCount, countRef] = useStateRef(5)
const [gsapCount, setGsapCount] = useState(0)
useLayoutEffect(() => {
const ctx = gsap.context(() => {
gsap.to('.box', {
x: 200,
repeat: -1,
onRepeat: () => setGsapCount(countRef.current),
})
}, app)
return () => ctx.revert()
}, [])
useMatchMedia
GSAP MatchMedia
Usage:
import { gsap } from 'gsap'
import { useMatchMedia } from 'gsap-react'
import { useLayoutEffect, useRef } from 'react'
function App() {
const ref = useRef<HTMLDivElement>(null)
const mm = useMatchMedia(ref)
useLayoutEffect(() => {
mm.add('(min-width: 768px)', () => {
gsap.to(q('.box'), { x: 200 })
})
return () => mm.revert()
}, [])
return (
<div ref={ref}>
<div className="box">Box 1</div>
</div>
)
}
useMergeRefs
Merge multiple refs, useful especially when using with forwardRef.
Usage:
import { gsap } from 'gsap'
import { useMergeRefs } from 'gsap-react'
import { forwardRef, useLayoutEffect, useRef } from 'react'
const Button = forwardRef(({ children, ...props }, ref) => {
const internalRef = useRef<HTMLButtonElement>(null)
const refs = useMergeRefs(ref, internalRef)
useLayoutEffect(() => {
let ctx = gsap.context(() => {}, internalRef)
}, [])
return (
<button ref={refs} {...props}>
<span className="button-text">{children}</span>
</button>
)
})
useIsomorphicLayoutEffect
Server side rendering (SSR)
Usage:
import { gsap } from 'gsap'
import { useIsomorphicLayoutEffect } from 'gsap-react'
import { useRef } from 'react'
function App() {
const app = useRef()
useIsomorphicLayoutEffect(() => {
const ctx = gsap.context(() => {
gsap.from('.box', { opacity: 0 })
}, app)
return () => ctx.revert()
}, [])
return (
<div className="app" ref={app}>
<div className="box">Box 1</div>
</div>
)
}
For more information, visit GSAP Hooks.
Components
SmoothScroll
This component uses GSAP ScrollSmoother
that applies scroll smoothing functionality and easily create elements with different scrolling speed or parallax effects, see docs. Under the hood it register the required plugins gsap.registerPlugin(ScrollTrigger, ScrollSmoother)
🔵 NOTE: This component needs a Club GreenSock membership.
Usage:
import { SmoothScroll } from 'gsap-react'
function App() {
return (
<SmoothScroll>
<div className="box" data-speed={0.6}>
Box 1
</div>
<div className="box" data-speed={0.8}>
Box 2
</div>
<div className="box" data-speed={1.2}>
Box 3
</div>
</SmoothScroll>
)
}
It accepts options
props for customizing the ScrollSmoother
. You can also disable the initial wrapper by setting the props noInitialWrapper
to true
if you plan to create your own wrapper element, just make sure to provide wrapper
and content
selector inside the options
props. default is #smooth-wrapper
and #smooth-content
.
Usage with NextJS 13.1 app dir:
First create a AppWrapper.tsx
and add "use client" directive at the top.
'use client'
import { SmoothScroll } from 'gsap-react'
interface AppWrapperProps {
children?: React.ReactNode
}
function AppWrapper({ children }: AppWrapperProps) {
return <SmoothScroll>{children}</SmoothScroll>
}
And import it in your root layout file.
function RootLayout({ children }: { children?: React.ReactNode }) {
return (
<html lang="en">
<head />
<body>
<AppWrapper>{children}</AppWrapper>
</body>
</html>
)
}
Usage along side with ScrollTrigger
:
You may encounter some issues when you have a component that uses ScrollTrigger
. To fix this we need to wait for ScrollSmoother
plugin to initialize, we can use the useSmoothScroll
hook to get the state of the smoother.
'use client'
import { gsap } from 'gsap'
import { useIsomorphicLayoutEffect, useSmoothScroll } from 'gsap-react'
import { useRef } from 'react'
function MyComponent() {
const { smoother } = useSmoothScroll()
const ref = useRef<HTMLDivElement>(null)
useIsomorphicLayoutEffect(() => {
if (!smoother) return
let ctx = gsap.context(() => {
gsap.to('.box', {
scale: 2,
scrollTrigger: {
trigger: ref.current,
},
})
}, ref)
return () => ctx.revert()
}, [smoother])
return (
<div ref={ref}>
<div className="box" />
</div>
)
}
Don't forget the 'use client' directive when using app dir in NextJS.
Contributing
Accepting PRs 💜