title: Infinite Scroll from Scratch in Reactjs w/ Intersection Observer
body: <p><strong>Background:</strong> I built an infinite scroller using intersection observer for the purpose of re-using dom nodes (aka windowing). When a div scrolls off the top of the viewport it gets absolutely positioned to the end of the sequence of divs, and vice versa for divs that exit the bottom.</p>
  
  <p><strong>The problem:</strong> If you scroll upward too quickly you scroll past the divs altogether. Meanwhile this doesn't happen if you scroll down too quickly. Having trouble figuring out why. </p>
  
  <p>Codesandbox (original): <a href="https://codesandbox.io/s/cranky-pasteur-wckzm" rel="nofollow noreferrer">https://codesandbox.io/s/cranky-pasteur-wckzm</a><br>
  Codesandbox (updated): <a href="https://codesandbox.io/s/infinite-scroll-intersection-observer-p15bm" rel="nofollow noreferrer">https://codesandbox.io/s/infinite-scroll-intersection-observer-p15bm</a></p>
  
  <p>The code (updated):</p>
  
  <pre><code>/* eslint no-unused-vars: 0 */
  /* eslint react-hooks/exhaustive-deps: 0 */
  /* eslint no-sequences: 0 */
  
  import React, { useState, useEffect } from "react";
  import "./styles.css";
  
  const App = () =&gt; {
    useEffect(() =&gt; {
      const divs = document.querySelectorAll('.abc')
  
      const options = {
        root: null,
        threshold: 0,
        rootMargin: '0px'
      }
  
      let observer
      if (observer) observer.disconnect()
      observer = new IntersectionObserver(entries =&gt; {
        entries.forEach(entry =&gt; {
          if (entry.isIntersecting || window.pageYOffset === 0) return
  
          entry.target.onclick = function(){console.log(entry)}
          const firstDiv = entry.target.parentNode.firstElementChild
          const lastDiv = entry.target.parentNode.lastElementChild
          const lastDivTopAmount = Number(lastDiv.style.top.split('').slice(0, -2).join(''))
          const firstDivTopAmount = Number(firstDiv.style.top.split('').slice(0, -2).join(''))
  
          if (entry.boundingClientRect.top &lt; 0) {
            console.log('element intersected top')
            firstDiv.style.top = `${lastDivTopAmount+320}px`
            firstDiv.parentNode.appendChild(firstDiv)
          }
  
          else {
            console.log('element intersected bottom')
            lastDiv.style.top = `${firstDivTopAmount-320}px`
            lastDiv.parentNode.prepend(lastDiv)
          }
        })
      }, options)
  
      divs.forEach(div =&gt; {
        observer.observe(div)
      })
  }, [])
  
    return (
      &lt;div&gt;
        &lt;div className="visibleRows"&gt;
          &lt;div 
            style={{top: '0px', backgroundColor: 'blue', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-1 abc"
          /&gt;
          &lt;div
            style={{top: '320px', backgroundColor: 'red', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-2 abc"
          /&gt;
          &lt;div
            style={{top: '640px', backgroundColor: 'green', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-3 abc"
          /&gt;
          &lt;div
            style={{top: '960px', backgroundColor: 'purple', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-4 abc"
          /&gt;
          &lt;div
            style={{top: '1280px', backgroundColor: 'yellow', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-5 abc"
          /&gt;
          &lt;div 
            style={{top: '1600px', backgroundColor: 'pink', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-6 abc"
          /&gt;
          &lt;div 
            style={{top: '1920px', backgroundColor: 'orange', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-7 abc"
          /&gt;
          &lt;div 
            style={{top:'2240px', backgroundColor: 'cyan', height: '320px', width: '580px', outline: '4px solid pink'}}
            className="baby-div-8 abc"
          /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    );
  };
  
  export default App;
  </code></pre>
  
  <p>Styles.css</p>
  
  <pre><code>.abc {
    position: absolute;
    height: 320px;
    width: 580px;
    outline: 4px solid pink;
  }
  </code></pre>