<div id="root" class="panel center text-center"></div>
.app {
  padding: 10px;
}

.box {
  margin: 10px 0;
}
const { useLayoutEffect, useEffect, useRef, forwardRef } = React;

const FadeIn = forwardRef(({ children, stagger = 0, x = 0 }, ref) => {
  const el = useRef();
  const animation = useRef();
  
  useLayoutEffect(() => {    
    animation.current = gsap.from(el.current.children, { 
      opacity: 0,
      stagger, 
      x 
    });        
  }, []);
  
  useEffect(() => {
    
    // forward the animation instance
    if (typeof ref === "function") {
      ref(animation.current);
    } else if (ref) {
      ref.current = animation.current;
    }
  }, [ref]);
  
  return <span ref={el}>{children}</span>
});

function App() {  
  
  const animation = useRef();
     
  const toggle = () => {
    animation.current.reversed(!animation.current.reversed());
  };
  
  return (
    <div className="app">
      <div>
        <button onClick={toggle}>Toggle</button>
      </div>
      <FadeIn stagger={0.1} x={100} ref={animation}>
        <div className="box">Box 1</div>
        <div className="box">Box 2</div>
      </FadeIn>
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));
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/17.0.2/umd/react.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js