From 018be7f1c3a8b399a9f38d7fa524e6f2908d95c3 Mon Sep 17 00:00:00 2001 From: Foysal Zihak <67580891+fzihak@users.noreply.github.com> Date: Sat, 4 Apr 2026 14:02:57 +0600 Subject: [PATCH] =?UTF-8?q?fix(admin):=20use=20infinite=20scroll=20for=20c?= =?UTF-8?q?ontent=20list=20to=20support=20large=20dat=E2=80=A6=20(#135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(admin): use infinite scroll for content list to support large datasets * chore: apply copilot review suggestions and add changeset --- .changeset/fix-infinite-pagination.md | 5 +++++ packages/admin/src/router.tsx | 29 +++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-infinite-pagination.md diff --git a/.changeset/fix-infinite-pagination.md b/.changeset/fix-infinite-pagination.md new file mode 100644 index 0000000..a243360 --- /dev/null +++ b/.changeset/fix-infinite-pagination.md @@ -0,0 +1,5 @@ +--- +"@emdash-cms/admin": patch +--- + +Fix content list for large collections by implementing infinite scroll pagination diff --git a/packages/admin/src/router.tsx b/packages/admin/src/router.tsx index bf82584..941c78f 100644 --- a/packages/admin/src/router.tsx +++ b/packages/admin/src/router.tsx @@ -235,9 +235,24 @@ function ContentListPage() { // Default to defaultLocale when i18n is enabled and no locale specified const activeLocale = i18n ? (localeParam ?? i18n.defaultLocale) : undefined; - const { data, isLoading, error } = useQuery({ + const { + data, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + isLoading, + error, + } = useInfiniteQuery({ queryKey: ["content", collection, { locale: activeLocale }], - queryFn: () => fetchContentList(collection, { locale: activeLocale }), + queryFn: ({ pageParam }) => + fetchContentList(collection, { + locale: activeLocale, + cursor: pageParam as string | undefined, + limit: 100, + }), + initialPageParam: undefined as string | undefined, + getNextPageParam: (lastPage) => lastPage.nextCursor, + enabled: !!manifest, }); // Fetch trashed items @@ -327,14 +342,20 @@ function ContentListPage() { }); }; + const items = React.useMemo(() => { + return data?.pages.flatMap((page) => page.items) || []; + }, [data]); + return ( void fetchNextPage()} trashedCount={trashedData?.items?.length || 0} onDelete={(id) => deleteMutation.mutate(id)} onRestore={(id) => restoreMutation.mutate(id)}