Components
Loading preview...
to used to manage large list and to automatically trigger next request when reaching the bottom of page #### Props - `items`: Array of data - `isPending`: Boolean for loading state - `itemsCount`: Total number of items available on the server ("COUNT" aggregation function in sql) - `loadMore`: Function to call when more items need to be loaded - `className`: Optional CSS class names - `children`: React children elements
@YoucefBnm
npx shadcn@latest add https://21st.dev/r/youcefbnm/infinite-scroll-container"use client"
import * as React from "react"
import {InfiniteScrollContainer,InifniteScrollContainerCell} from "@/components/ui/infinite-scroll-container"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
interface Post {
id: number
userId: number
title: string
body: string
}
const BASE_URL = "https://jsonplaceholder.typicode.com/posts"
const LIMIT = 10
export function InfiniteScrollContainerDemo() {
const [posts, setPosts] = React.useState<Post[]>([])
const [page, setPage] = React.useState<number>(0)
const [totalCount, setTotalCount] = React.useState<number | null>()
const [isLoading, setIsLoading] = React.useState<boolean>(false)
async function fetchData() {
setIsLoading(true)
const start = page * LIMIT
try {
const response = await fetch(
`${BASE_URL}?_start=${start}&_limit=${LIMIT}`
)
const totalItems = response.headers.get("x-total-count")
const data = await response.json()
setTotalCount(Number(totalItems))
setPosts((prevPosts) => [...prevPosts, ...data])
setPage((prevPage) => prevPage + 1)
} catch (error) {
console.error("Error fetching data:", error)
} finally {
setIsLoading(false)
}
}
React.useEffect(() => {
fetchData()
}, [])
return (
<InfiniteScrollContainer
items={posts}
isPending={isLoading}
itemsCount={totalCount}
loadMore={fetchData}
className="container mx-auto grid grid-cols-[repeat(auto-fill,minmax(220px,1fr))] gap-2 p-12"
>
{posts.map((post, index) => (
<InifniteScrollContainerCell isPending={isLoading} key={`${post.id}-${index}`}>
<Card>
<CardHeader>
<CardTitle className="text-muted">#{post.id}</CardTitle>
<CardDescription>{post.title}</CardDescription>
</CardHeader>
<CardContent className="text-sm text-foreground">
<p>{post.body}</p>
</CardContent>
</Card>
</InifniteScrollContainerCell>
))}
</InfiniteScrollContainer>
)
}