Skip to content

Instantly share code, notes, and snippets.

@rossnelson
Created January 25, 2024 03:58
Show Gist options
  • Save rossnelson/c03583e022aac0addd4f8644b0a91574 to your computer and use it in GitHub Desktop.
Save rossnelson/c03583e022aac0addd4f8644b0a91574 to your computer and use it in GitHub Desktop.
forever-scroll
import { createRef, useEffect, useState } from 'react';
export function useScreenEnter(callback) {
const scrollRef = createRef();
const loaderRef = createRef();
const [more, hasMore] = useState(true);
function activate() {
if (
loaderRef.current &&
isInViewPort(
scrollRef.current.getBoundingClientRect(),
loaderRef.current.getBoundingClientRect()
) &&
more
) {
callback();
}
}
useEffect(() => {
if (!scrollRef.current) return;
const { current } = scrollRef;
current.addEventListener('scroll', activate);
return () => current.removeEventListener('scroll', activate);
});
return {
scrollRef,
loaderRef,
hasMore
};
}
function isInViewPort(scrollerRect, loaderRect) {
if (
Math.round(scrollerRect.bottom) >= Math.round(loaderRect.bottom) &&
loaderRect.top >= 0 &&
loaderRect.left >= 0
)
return true;
return false;
}
const [meta, setMeta] = useState({ last: false });
const [content, setContent] = useState([]);
const { scrollRef, loaderRef, hasMore } = useScreenEnter(() => {
// do something to get more
const setItems = async items => {
const { content: newContent, ...meta } = items;
setMeta(meta);
hasMore(!meta.last);
setContent([...content, ...newContent]);
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment