Implement an Infinite Scroll component with real-time data fetching.
ReactHooksAPIPerformance
Live Interactive Demo
Loading Demo...
Implementation
typescript.tsx
import React, { useEffect, useState, useRef, useCallback } from 'react';
const InfiniteScroll = () => {
const [photos, setPhotos] = __PH_34__([]);
const [loading, setLoading] = __PH_35__(false);
const [page, setPage] = __PH_36__(1);
const observer = __PH_37__();
const lastElementRef = __PH_38__(node => {
if (loading) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
setPage(prev => prev + 1);
}
});
if (node) observer.current.observe(node);
}, [loading]);
__PH_39__(() => {
const fetchPhotos = async () => {
setLoading(true);
const res = await fetch(`https://picsum.photos/v2/list?page=${page}&limit=10`);
const data = await res.json();
setPhotos(prev => [...prev, ...data]);
setLoading(false);
};
fetchPhotos();
}, [page]);
return (
<div className='grid grid-cols-2 gap-4'>
{photos.map((photo, i) => (
<img
key={photo.id}
ref={i === photos.length - 1 ? lastElementRef : null}
src={photo.download_url}
alt={photo.author}
className='rounded-lg w-full h-48 object-cover'
/>
))}
{loading && <p>Loading...</p>}
</div>
);
};The Core Concept
Infinite scrolling allows users to load content continuously as they scroll down the page, improving UX for large datasets. Key concepts include:
1. **Intersection Observer API**: more performant than scroll event listeners as it doesn't run on every pixel scroll. 2. **Loading States**: managing 'isLoading' to prevent duplicate requests. 3. **Page Management**: tracking the current page index for the API. 4. **Cleanup**: ensuring observers are disconnected when the component unmounts.
In this implementation, we use `picsum.photos` to fetch images and a ref-based 'trigger' element at the bottom of the list.