Skip to content

Instantly share code, notes, and snippets.

@dannysofftie
Last active June 21, 2021 03:40
Show Gist options
  • Save dannysofftie/83d55768eae7ac9c3885ef7d157bba84 to your computer and use it in GitHub Desktop.
Save dannysofftie/83d55768eae7ac9c3885ef7d157bba84 to your computer and use it in GitHub Desktop.

Use this hook to watch element intersection

export const useIntersectionObserver = ({ root, target, onIntersect, threshold = 0.4, rootMargin = '0px', enabled = null }) => {
  useEffect(() => {
    if (!enabled) {
      return;
    }
    const observer = new IntersectionObserver((entries) => entries.forEach((entry) => entry.isIntersecting && onIntersect()), {
      root: root?.current,
      rootMargin,
      threshold,
    });
    const el = target?.current;
    if (!el) {
      return;
    }
    observer.observe(el);
    return () => {
      observer.unobserve(el);
    };
  }, [target?.current, enabled]);
};

Use above hook as below, in your page

  const [currentPage, setPage] = useState(1);
  const [endPage, setEndPage] = useState(false);
  const [nextPageLoading, updatePageLoadingState] = useState(false);
  const [localData, updateLocalData] = useState([]);
  const { data: queryData, isLoading } = useDataQuery({ page: currentPage });

  const [loadMoreRef, rootRef] = [useRef(null), useRef(null)];

  useIntersectionObserver({
    onIntersect: () => {
      if (localData?.length >= 20 * currentPage && !nextPageLoading) {
        setPage(currentPage + 1);
        updatePageLoadingState(true);
        setEndPage(false);
      } else {
        updatePageLoadingState(false);
        setEndPage(true);
      }
    },
    root: rootRef?.current,
    target: loadMoreRef,
    enabled: localData,
  });
  
  useEffect(() => {
    const dedupedData = Array.from(
      [...localData, ...(queryData || [])].reduce((m, t) => {
        const removed = m?.filter((i) => i?.id !== t?.id);
        return [...removed, t];
      }, []),
    );
    updateLocalData(dedupedData);
    updatePageLoadingState(false);
  }, [queryData]);

Wrap the page with this component

<section ref={rootRef}>
  // your code here
  // loop through localData above here
  // 
</section>

Place this at the bottom of the page

 {/* load more ref */}
 <section ref={loadMoreRef} />

Example

<Fragment>
 <section ref={rootRef}>
  // your code here
  // loop through localData above here
  // 
 </section>
 {/* load more ref */}
 <section ref={loadMoreRef} />
</Fragment>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment