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

.app {
  padding: 10px;
}

.box {
  margin: 30px 0;
}
const { useLayoutEffect, useRef } = React;

const Box = ({ children, className, anim }) => {
  return <div className={"box " + className } data-animate={ anim }>{children}</div>;
};

function App() {
  const app = useRef();
  
  useLayoutEffect(() => {
    
    const ctx = gsap.context(() => {
      // Target the two specific elements we have asigned the animate class
      gsap.to("[data-animate='rotate']", {
        rotation: 360,
        repeat: -1,
        repeatDelay: 1,
        yoyo: true
      });
      
      gsap.to("[data-animate='move']", {
        x: 100,
        repeat: -1,
        repeatDelay: 1,
        yoyo: true
      });
      
      gsap.set(".dont-animate", {
        backgroundColor: 'red'
      });
      
    }, app);// <- Scope!
    
    return () => ctx.revert();
  }, []);
  
  return (
    <div className="app" ref={app}>
      <Box anim="rotate">Box</Box>
      <Box className="dont-animate">Don't Animate Me</Box>
      <Box anim="move">Box</Box>
    </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