<div id="app"></div>
.wrapper {
  background: #fff;
  height: 300px;
  padding: 400px 12px 12px 12px;
  overflow-y: scroll;
  border: 1px solid #ddd;
}

.target {
  transition: all 0.4s;
}
const Sample = () => {
  const [opacity, setOpacity] = React.useState(false);
  
  const ref = React.useRef<HTMLDivElement>(null);
  
  React.useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          setOpacity(true);
        } else {
          setOpacity(false);
        }
      })
    }, {
      rootMargin: '20px',
    });

    const el = ref.current;

    if (!el) return;
    
    observer.observe(el);
  
    return () => observer.unobserve(el);
  }, []);

  return (
    <div>
      <h1>Intersection Observer API sample</h1>
      <div className='wrapper'>
        <div ref={ref} style={{ opacity: opacity ? 1 : 0}} className='target'>見えたら処理が発火する</div>
      </div>
    </div>
  )
}

ReactDOM.render(<Sample />, document.querySelector('#app'))
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/typescript/4.9.5/typescript.min.js