I think what semantically confused me is that there are two ways to make ScrollTrigger tweens. One that is from the ScrollTrigger namespace and one that "overrides" the core methods through the scrollTrigger object. I put that in quotes because it's likely not what happens, but that was my assumption watching the video on ScrollTrigger and perusing the documentation page while I was making my client's project.
I respectfully disagree. This is my first time using gsap, so clearly I have a learning curve and my opinion is only from a seasoned developer coming with a fresh set of eyes onto a mature library. But, in react it's memory efficient to declare all of your objects on mount and then to use and modify them as needed. A prime example (in pseudocode) is this:
import React, { useEffect, useRef, useState } from 'react';
// Assume gsap is loaded
export default function App() {
const domElement = useRef();
const refs = useRef({ timeline: null });
const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
useEffect(setup, []);
function setup() {
refs.current.timeline = gsap.timeline();
window.addEventListener('resize', resize, false);
return unmount;
function unmount() {
window.removeEventListener('resize', resize, false);
}
function resize() {
const w = window.innerWidth;
const h = window.innerHeight;
setWidth(w);
setHeight(h);
timeline.clear();
// Change animation logic based
// on viewport dimensions (i.e portrait / landscape)
if (w > h) {
// Move horizontally
timeline.to(domElement.current.style, { left: 25 });
} else {
// Move vertically
timeline.to(domElement.current.style, { top: 25 });
}
}
}
return (
<div ref={ domElement } className="app" />
);
}
Perhaps the gsap way is to destroy the timeline and make a new one every time the page resizes? In the project I was working on (which brought me to raise these questions), the eventCallback method added flexibility for this use case. Though, it was unable to handle ScrollTrigger events like onEnter.