react-infinite-scroll-hook
react-infinite-scroll-hook copied to clipboard
rootMargin doesn't work when root default to null
See this example in codesandbox
https://codesandbox.io/s/try-react-infinite-scroll-hook-4ekfj1?file=/src/App.jsx:1374-1384
This is a common pitfall when using rootMargin
without root
specified
Little rules of Interception Observer API
:
root
default to viewport while the viewport doesn't have any margin, so set rootMargin
to any value will always fallback to 0px
.
I may implemented a better version of this hook
Easier to use, less properties required, same ability, here is a simple usage:
export default function App() {
const [list, setList] = useState([...Array(11).keys()])
const { containerRef, isLoading } = useInfiniteScroll({
async onLoadMore() {
const res = await fetchList(list.slice(-1)[0])
setList(list.concat(res))
},
})
return (
<div className="App">
<List ref={containerRef}>
{list.map((n) => (
<Item key={n}>{n}</Item>
))}
{isLoading && <Loading>Loading ...</Loading>}
</List>
</div>
)
Use offset
against rootMargin
Will load more while to bottom offset '200px'
const { containerRef, isLoading } = useInfiniteScroll({offset: '200px'})
...
All css size units available
-
offset: 200px
✅ -
offset: 20%
✅ -
offset: 20vh
✅ -
offset: 20cm
✅ - ...
Extra bonus
Using offset: 200px
as absolute distance to bottom offset.
Using offset: 20%
as relative distance to bottom offset, it will insure the trigger point always stick to the 80% height of scrollbar.
Stop while finished
const { containerRef, isLoading } = useInfiniteScroll({shouldStop: isFetchEnd})
...
return (
<div className="App">
<List ref={containerRef}>
{list.map((n) => (
<Item key={n}>{n}</Item>
))}
{(isLoading || !isFetchEnd) && <Loading>Loading ...</Loading>}
</List>
</div>
)
Talk is cheap, check out the source code :)
https://codesandbox.io/s/better-react-infinite-scroll-hook-kgup0w?file=/src/useInfiniteScroll.js
Update the next day:
I made it to become another independent library https://github.com/iamyoki/infinite-scroll-hook