<div id="root" class="panel center text-center"></div>
body{
  margin: 0;
  padding: 0;
  height: 100vh;
}

.app {
  padding: 1px;
  width: 100%;
}

.box {
  margin: 10px;
  padding: 0.5rem;
  width: 120px;
  height: 120px;
}
console.clear();
const { useEffect, useLayoutEffect, useRef, useState } = React;

function App() {
  const app = useRef();
  
  const [count, setCount] = useState(0);
  const [delayedCount, setDelayedCount] = useState(0);

  // only runs on first render
  useLayoutEffect(() => {
    const ctx = gsap.context(() => {
      gsap.to(".box-1", { rotation: "+=360" });
    }, app);
    return () => ctx.revert();
  }, []);

  // runs on first render and every time delayedCount changes
  useLayoutEffect(() => {
    const ctx = gsap.context(() => {
      gsap.to(".box-2", { rotation: "+=360" });
    }, app);
    return () => ctx.revert();
  }, [delayedCount]);

  // runs on every render
  useLayoutEffect(() => {
    const ctx = gsap.context(() => {
      gsap.to(".box-3", { rotation: "+=360" });
    }, app);
    return () => ctx.revert();
  });

  useEffect(() => {
    const timer = setTimeout(() => {
      setDelayedCount(count);
    }, 1000);

    return () => clearTimeout(timer);
  }, [count]);

  return (
    <div className="app" ref={app}>
      <div>
        <button onClick={() => setCount(count + 1)}>Click to trigger a render</button>
      </div>
      <p>Count: {count}</p>
      <p>Delayed Count: {delayedCount}</p>
      <p>Renders: {1 + delayedCount + count}</p>
      <div className="flex-row">
        <div className="box box-1 purple">First render</div>
        <div className="box box-2 blue">First render & delayed count change</div>
        <div className="box box-3 red">Every render</div>
      </div>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
View Compiled

External CSS

  1. https://codepen.io/GreenSock/pen/gOWxmWG.css

External JavaScript

  1. https://unpkg.co/gsap@3/dist/gsap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js