mirror of
https://github.com/jnsahaj/tweakcn.git
synced 2026-08-28 23:02:07 +08:00
feat: add infinite scroll to community page
Replace the manual "Load More" button with IntersectionObserver-based infinite scroll using a sentinel div with 200px root margin for pre-fetching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useCommunityThemes } from "@/hooks/themes";
|
||||
import type { CommunitySortOption } from "@/types/community";
|
||||
import { useQueryState, parseAsStringLiteral } from "nuqs";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -37,6 +38,25 @@ export function CommunityThemesContent() {
|
||||
|
||||
const themes = data?.pages.flatMap((page) => page.themes) ?? [];
|
||||
|
||||
const sentinelRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const sentinel = sentinelRef.current;
|
||||
if (!sentinel) return;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) {
|
||||
fetchNextPage();
|
||||
}
|
||||
},
|
||||
{ rootMargin: "200px" }
|
||||
);
|
||||
|
||||
observer.observe(sentinel);
|
||||
return () => observer.disconnect();
|
||||
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
@@ -134,25 +154,11 @@ export function CommunityThemesContent() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{hasNextPage && (
|
||||
<div className="flex justify-center pt-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onClick={() => fetchNextPage()}
|
||||
disabled={isFetchingNextPage}
|
||||
>
|
||||
{isFetchingNextPage ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Loading...
|
||||
</>
|
||||
) : (
|
||||
"Load More"
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<div ref={sentinelRef} className="flex justify-center pt-4">
|
||||
{isFetchingNextPage && (
|
||||
<Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user