Files
ponytail/examples/infinite-scroll.md
T
Jesus cornelio b345e49385 examples: add 6 new over-engineering survivors + platform-native guide (#109)
New examples (examples/):
- modal-dialog: <dialog> vs Radix/react-modal
- url-params: URLSearchParams vs query-string
- number-formatting: Intl.NumberFormat vs numeral
- infinite-scroll: IntersectionObserver vs react-infinite-scroll-component
- deep-clone: structuredClone vs lodash.cloneDeep / JSON hack
- group-by: Object.groupBy vs lodash.groupBy

New doc (docs/platform-native.md):
Comprehensive reference of platform-native solutions across HTML elements,
CSS, Browser APIs, Node.js stdlib, Python stdlib, and database features.
Covers 60+ cases where the platform already has what developers reach for
a package to do.
2026-06-19 00:24:29 +02:00

1.5 KiB

Infinite Scroll

Task: "Load more items when the user scrolls to the bottom."

Without Ponytail

npm install react-infinite-scroll-component
import InfiniteScroll from "react-infinite-scroll-component";

export function Feed({ items, fetchMore, hasMore }) {
  return (
    <InfiniteScroll
      dataLength={items.length}
      next={fetchMore}
      hasMore={hasMore}
      loader={<Spinner />}
      endMessage={<p>No more items</p>}
      scrollThreshold={0.9}
    >
      {items.map(item => <Card key={item.id} item={item} />)}
    </InfiniteScroll>
  );
}

A dependency to watch scroll position and fire a callback.

With Ponytail

// ponytail: IntersectionObserver does this, no scroll listener needed
import { useEffect, useRef } from "react";

export function Feed({ items, fetchMore, hasMore }) {
  const sentinel = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting && hasMore) fetchMore();
    });
    if (sentinel.current) observer.observe(sentinel.current);
    return () => observer.disconnect();
  }, [hasMore, fetchMore]);

  return (
    <>
      {items.map(item => <Card key={item.id} item={item} />)}
      <div ref={sentinel} />
    </>
  );
}

1 dependency → 0 dependencies. IntersectionObserver fires only when the sentinel enters the viewport — no scroll event, no throttling, no jank. Ships in every browser. The library wraps exactly this API.