After a couple of days I finally was able to achieve an infinite scroll on my project. Here is yet another time saving snippet that you can use to achieve the same in a shorter time frame. As usual this is not a tutorial but a quick post to help a fellow developer save time on implementing an infinite scroll. You'll have to edit the code to fit the needs of your project.
I am using nextUI for the frontend components.
First we'll create a dummy user object
interface User {
id: number;
name: string;
}
Then I create a function to generate dummy data to populate the users array with user objects.
const generateDummyData = (start: number, count: number): User[] => {
return Array.from({ length: count }, (_, i) => ({
id: start + i,
name: `User ${start + i + 1}`,
}));
};
Time to implement a function called loadMoreUsers to fetch and append more user data as one scrolls down the page. I have simulated an api call time delay of 2 seconds.
const loadMoreUsers = async () => {
if (loading || page >= 10) return;
setLoading(true);
await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate 2-second delay
const newUsers = generateDummyData(page * 10, 10);
setUsers((prevUsers) => [...prevUsers, ...newUsers]);
setPage((prevPage) => prevPage + 1);
setLoading(false);
};
Next step is to use useEffect to load initial user data when the component mounts and to handle scrolling to load more users...
useEffect(() => {
if (!initialized.current) {
initialized.current = true
loadMoreUsers();
}
}, []);
useEffect(() => {
const handleScroll = () => {
if (
window.innerHeight +
Math.max(
window.pageYOffset,
document.documentElement.scrollTop,
document.body.scrollTop
) >
document.documentElement.offsetHeight - 100
) {
if (page < 10 && page > 0) {
loadMoreUsers();
}
} else {
return;
}
};
Lastly we add an event listener for the scrollbar...
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [page, loading]);
That's it. Below is the full script...You can save it as a seperate file in the utils or components and simply import it to your project.
import { Card, CardBody,Spinner,Button } from '@nextui-org/react';
import { useEffect, useState, useRef } from 'react';
interface User {
id: number;
name: string;
}
const generateDummyData = (start: number, count: number): User[] => {
return Array.from({ length: count }, (_, i) => ({
id: start + i,
name: `User ${start + i + 1}`,
}));
};
const UserListPage = () => {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(0);
const initialized = useRef(false)
const loadMoreUsers = async () => {
if (loading || page >= 10) return;
setLoading(true);
await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate 2-second delay
const newUsers = generateDummyData(page * 10, 10);
setUsers((prevUsers) => [...prevUsers, ...newUsers]);
setPage((prevPage) => prevPage + 1);
setLoading(false);
};
useEffect(() => {
if (!initialized.current) {
initialized.current = true
loadMoreUsers();
}
}, []);
useEffect(() => {
const handleScroll = () => {
if (
window.innerHeight +
Math.max(
window.pageYOffset,
document.documentElement.scrollTop,
document.body.scrollTop
) >
document.documentElement.offsetHeight - 100
) {
if (page < 10 && page > 0) {
loadMoreUsers();
}
} else {
return;
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [page, loading]);
return (
<div>
{users.map((user) => (
<Card key={user.id}>
<CardBody>
<p>{user.name}</p>
</CardBody>
</Card>
))}
{loading ? (<Spinner />) : (<Button onClick={loadMoreUsers}>Load more</Button> )}
</div>
);
};
export default UserListPage;
That's it folks....Now you can proceed to the other interesting parts of your project. Once I implement the api version I shall share as well
Top comments (0)