I've been working with GSAP for quite some time now, utilizing the GSAP Premium Version. Specifically, I integrate GSAP into next.js applications (SSR). I've reviewed numerous documentation resources on GSAP/next.js and believe I'm employing GSAP according to best practices. For the most part, everything functions smoothly.
However, I'm encountering issues with the Scrolltrigger. Whenever I bind animations to a Scrolltrigger that uses a React Ref (useRef) as a "trigger," errors consistently arise.
During the initial load of a very long page, components on the page utilizing a Scrolltrigger sometimes throw an error: "Cannot read properties of undefined (reading 'end')." This problem seems to be related to the Scrolltrigger not having an element available. It is also the case that if I set the trigger via React ref, an error is thrown, but if the trigger is set via CSS class, no error is displayed.
scrollTrigger: {
invalidateOnRefresh: true,
start: 'top center',
trigger: containerRef.current // throws errors sometimes
}
scrollTrigger: {
invalidateOnRefresh: true,
start: 'top center',
trigger: '.container' // throws no error, seems not working properly all the time
}
According to the documentation, there's an option to set nullTargetWarn: false in gsap.config, but this doesn't suppress the errors being thrown. Somehow, this seems to be related to SSR of the component, as the errors seem to disappear when I don't load the React component via SSR.
I'm employing common patterns, such as "useIsomorphicLayoutEffect" or checking within the hook if the Ref element exists. However, this doesn't seem to resolve the issue either.
import { useEffect, useLayoutEffect } from 'react'
export const useIsomorphicLayoutEffect =
typeof window !== 'undefined' ? useLayoutEffect : useEffect
const List = ({ title, titleSize = 2, subtitle, items }) => {
const containerRef = useRef()
const listItemsRef = useRef([])
useIsomorphicLayoutEffect(() => {
if (!containerRef.current) return
const ctx = gsap.context(() => {
gsap.to(
listItemsRef.current,
{
clipPath: 'polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)',
duration: 1,
opacity: 1,
scrollTrigger: {
invalidateOnRefresh: true,
start: 'top center',
trigger: containerRef.current
},
stagger: 0.2,
y: 0
},
0
)
}, containerRef)
return () => ctx.revert()
}, [])
return (
<div ref={containerRef}>
...
gsap.config({
nullTargetWarn: false
})
The error is quite ugly because on the production environment, the entire frontend crashes if the error is thrown and not caught manually.
Does anyone have any tips on what might be causing this?