Infinite Scroll
Infinite scroll is a popular pattern for loading and displaying a large number of items without traditional pagination.
As the user scrolls down, new items are fetched and added to the end of the list. While Hyper-fetch doesn't have a
dedicated useInfiniteScroll hook out-of-the-box, you can easily implement this pattern by composing useSubmit to
load more data on demand.
What you'll learn
- How to implement a "Load More" feature for paginated data.
- How to use
useSubmitto manually trigger fetching for the next page. - How to append new data to an existing list in React state.
- How to manage loading states for a better user experience.
Implementation with useSubmit
A clean way to implement infinite scroll is to use the useSubmit hook to fetch new pages when the user clicks a "Load
More" button. This gives us precise control over when data is fetched.
function InfinitePostList() {
const [posts, setPosts] = React.useState([]);
const [page, setPage] = React.useState(1);
const [allLoaded, setAllLoaded] = React.useState(false);
// We use useSubmit to manually trigger the fetch for the next page
const { submit, submitting } = useSubmit(getPosts);
const loadMore = async () => {
const { data: newPosts } = await submit({ queryParams: { page, limit: 5 } });
if (newPosts && newPosts.length > 0) {
setPosts((prevPosts) => [...prevPosts, ...newPosts]);
setPage((prevPage) => prevPage + 1);
} else {
setAllLoaded(true);
}
};
// Load the first page on component mount
React.useEffect(() => {
loadMore();
}, []);
return (
<div className="border rounded-md">
<ul className="divide-y divide-gray-200">
{posts.map((post) => (
<li key={post.id} className="p-4">
<p className="font-bold">{post.title}</p>
<p>{post.body}</p>
</li>
))}
</ul>
{submitting && <p className="text-center p-4">Loading...</p>}
{!allLoaded && (
<div className="p-4 flex justify-center">
<button
className="px-6 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-400"
onClick={loadMore}
disabled={submitting}
>
{submitting ? "Loading..." : "Load More"}
</button>
</div>
)}
{allLoaded && posts.length > 0 && <p className="text-center p-4 text-gray-500">You've reached the end!</p>}
</div>
);
}
How it Works
- We maintain a
postsarray in our state to hold all the items and apagenumber to track which page to fetch next. - We use
useSubmitbecause it allows us to trigger the request manually via thesubmitfunction. This is perfect for a "Load More" button. - The
loadMorefunction callssubmitwith the currentpage. Thesubmitfunction is a promise, so we canawaitits result. - Once we get the
newPosts, we append them to our existingpostsarray and increment the page number for the next fetch. - If the API returns an empty array, we know we've reached the end, and we can stop showing the "Load More" button.
- A
useEffecthook is used to load the initial page of data when the component mounts.
This approach is robust and gives a great user experience by showing a growing list of items.
Congratulations!
You've learned how to build an infinite scroll feature with Hyper-fetch!
- You can create a "Load More" pattern for large datasets using
useSubmit. - You can manage paginated data from an API and display it in a single, growing list.
- You can manually trigger data fetching for creating interactive data-driven UIs.
