function PaginatedList() {
const [page, setPage] = React.useState(1)
const scrollEndRef = React.useRef(null)
const [loading, setLoading] = React.useState(true)
const [products, setProducts] = React.useState([])
const [error, setError] = React.useState(null)
const fetchData = async (page) => {
try {
setLoading(true)
const res = await fetch(
`https://dummyjson.com/products/?limit=40&skip=${(page - 1) * 40}`,
)
const data = await res.json()
if (res.ok) {
setProducts((prevItems) => [...prevItems, ...data.products])
}
setLoading(false)
} catch (error) {
setLoading(false)
if (error instanceof Error) {
setError(error)
}
}
}
const handleIntersection = (entries) => {
if (entries.some((entry) => entry.isIntersecting)) {
fetchData(page + 1)
}
}
React.useEffect(() => {
const observer = new IntersectionObserver(handleIntersection)
if (scrollEndRef.current) {
observer.observe(scrollEndRef.current)
}
return () => observer.disconnect()
}, [])
React.useEffect(() => {
fetchData(page)
}, [page])
console.log(products)
return (
<div>
<style>{`
.container {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 400px;
max-height: 500px;
overflow-y: auto;
margin: 40px auto;
padding: 0 20px;
}
.list {
list-style: none;
padding: 0;
margin: 0 0 16px;
}
.list li {
padding: 8px 0;
border-bottom: 1px solid #e5e7eb;
}
.list li:first-child {
border-top: 1px solid #e5e7eb;
}
`}</style>
<div className="container">
{loading && <div>Loading...</div>}
{error && <div>Error: {error.message}</div>}
<ul className="list">
{products.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
<div ref={scrollEndRef} />
</div>
</div>
)
}
export default function Demo() {
return <PaginatedList />
}