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.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Infinite Scroll
|
||||
|
||||
**Task:** "Load more items when the user scrolls to the bottom."
|
||||
|
||||
## Without Ponytail
|
||||
|
||||
```bash
|
||||
npm install react-infinite-scroll-component
|
||||
```
|
||||
|
||||
```jsx
|
||||
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
|
||||
|
||||
```jsx
|
||||
// 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.
|
||||
Reference in New Issue
Block a user