While searching ways to implement infinitely scrolling effect on the internet, I realized that many tutorials use additional libraries or hooks to handle this effect 🧐.
After trying several times, I mostly got it in a quite simple way. So, I decided to write this article to share with you how to implement the infinite scrolling effect in ReactJS without any additional hooks or libraries.
Idea
Before we jump into coding, we need to understand the concept to archive our goal. When the content of the page is longer than client view, our browser will allow us to scroll the client view to see the remaining content.
To create the effect, we just need to calculate the client view (viewport) position when user scrolls. If it reach the threshold, we trigger a fetching action to get more data. Thanks to the available web APIs, we can easily get the position from window
object.
Coding
To simple, we can define a threshold about 300px, 100px, any number you want, or you can use the height of the last item as the threshold.
We use window.scrollY
to detect the position of the client view (viewport), document.body.scrollHeight
for the scrollable height, and window.innerHeight
for the client view height.
Finally, we check the condition every time user scrolls, if the condition is satisfied, we call API to get more data.
Here is the implementation in my Pokémon project.
export function PokemonsPage() {
const [pokemons, setPokemons] = useState<Pokemon[]>([]);
const [loading, setLoading] = useState(false);
const offset = useRef(0);
const fetchData = async () => {
setLoading(true);
try {
const data = await getPokemons(offset.current);
const promises = data.results.map(async (result) => {
const detail = await getPokemonDetailByUrl(result.url);
return toPokemon(detail);
});
const _pokemons = await Promise.all(promises);
setPokemons((prev) => [...prev, ..._pokemons]);
if (_pokemons.length === 20) {
offset.current += 20;
}
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
const handleScroll = () => {
if (loading) return;
if (
window.scrollY + window.innerHeight >
document.body.scrollHeight - 300
) {
fetchData();
}
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [loading, pokemons]);
return (
<div className="p-6" id="view">
<List data={pokemons} />
</div>
);
}
And that's it for this article, I hope this simple implemtation can help you in your projects. Thank you for reading 🤩
Top comments (0)