@tanstack/react-virtual not displaying my virtual list

i have an announcement page where i am fetching all the announcements from the trpc's useInfiniteQuery hook and i am using @tanstack/react-virtual for rendering and refetching query i saw docs on trpc's use infinite query for implementing. link for the same - https://trpc.io/docs/v10/client/react/useInfiniteQuery also i saw the @tanstack/react-virtual for infinite query example. link for the same - https://tanstack.com/virtual/latest/docs/framework/react/examples/infinite-scroll and i modified them according them to my own needs i am able to get the data successfully from the backend but it is not rendering in my app code is below :- Backend Code
getBySociety: protectedProcedure
.input(
z.object({
societyId: z.string().cuid(),
limit: z.number().min(1).max(100).nullish(),
cursor: z.string().nullish(),
}),
)
.query(async ({ ctx: { db }, input: { societyId, cursor, limit } }) => {
const _limit = limit ?? 2;
const announcements = await db.announcement.findMany({
where: {
societyId,
},
take: _limit,
cursor: cursor ? { id: cursor } : undefined,
orderBy: {
createdAt: "desc",
},
select: {
id: true,
member: {
select: {
image: true,
name: true,
},
},
content: true,
attachments: { select: { name: true, uri: true } },
_count: {
select: { comments: true },
},
},
});

let nextCursor: typeof cursor | undefined = undefined;
if (announcements.length > _limit) {
const nextItem = announcements.pop();
nextCursor = nextItem!.id;
}

return {
announcements,
nextCursor,
};
}),
getBySociety: protectedProcedure
.input(
z.object({
societyId: z.string().cuid(),
limit: z.number().min(1).max(100).nullish(),
cursor: z.string().nullish(),
}),
)
.query(async ({ ctx: { db }, input: { societyId, cursor, limit } }) => {
const _limit = limit ?? 2;
const announcements = await db.announcement.findMany({
where: {
societyId,
},
take: _limit,
cursor: cursor ? { id: cursor } : undefined,
orderBy: {
createdAt: "desc",
},
select: {
id: true,
member: {
select: {
image: true,
name: true,
},
},
content: true,
attachments: { select: { name: true, uri: true } },
_count: {
select: { comments: true },
},
},
});

let nextCursor: typeof cursor | undefined = undefined;
if (announcements.length > _limit) {
const nextItem = announcements.pop();
nextCursor = nextItem!.id;
}

return {
announcements,
nextCursor,
};
}),
useInfiniteQuery | tRPC
- Your procedure needs to accept a cursor input of any type (string, number, etc) to expose this hook.
React TanStack Virtual Infinite Scroll Example | TanStack Virtual Docs
An example showing how to implement Infinite Scroll in React using TanStack Virtual.
3 Replies
notrebekahmikaelson
Frontend Code -
"use client";

import { useParams } from "next/navigation";
import { api } from "~/trpc/react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useRef, useEffect } from "react";
import AnnouncementSkeleton from "./AnnouncementSkeleton";

export default function AnnouncementContainer() {
const { id } = useParams<{ id: string }>();
const {
isLoading,
data,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
isFetching,
} = api.announcement.getBySociety.useInfiniteQuery(
{
societyId: id,
limit: 2,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
},
);

const allAnnouncements = data
? data.pages.flatMap((_announcement) => _announcement.announcements)
: [];

const parentRef = useRef(null);

const rowVirtualizer = useVirtualizer({
count: hasNextPage ? allAnnouncements.length + 1 : allAnnouncements.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 5,
overscan: 5,
debug: true,
});

useEffect(() => {
const [lastItem] = [...rowVirtualizer.getVirtualItems()].reverse();

if (!lastItem) {
return;
}

if (
lastItem.index >= allAnnouncements.length - 1 &&
hasNextPage &&
!isFetchingNextPage
) {
void fetchNextPage();
}
}, [
hasNextPage,
fetchNextPage,
allAnnouncements.length,
isFetchingNextPage,
rowVirtualizer.getVirtualItems(),
]);

return (
<>
{isLoading ? (
<AnnouncementSkeleton />
) : (
<div ref={parentRef}>
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
const isLoaderRow = virtualRow.index > allAnnouncements.length - 1;
const announcement = allAnnouncements[virtualRow.index];

return JSON.stringify(announcement);
})}
</div>
)}
{isFetching && !isFetchingNextPage ? <AnnouncementSkeleton /> : null}
</>
);
}
"use client";

import { useParams } from "next/navigation";
import { api } from "~/trpc/react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useRef, useEffect } from "react";
import AnnouncementSkeleton from "./AnnouncementSkeleton";

export default function AnnouncementContainer() {
const { id } = useParams<{ id: string }>();
const {
isLoading,
data,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
isFetching,
} = api.announcement.getBySociety.useInfiniteQuery(
{
societyId: id,
limit: 2,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
},
);

const allAnnouncements = data
? data.pages.flatMap((_announcement) => _announcement.announcements)
: [];

const parentRef = useRef(null);

const rowVirtualizer = useVirtualizer({
count: hasNextPage ? allAnnouncements.length + 1 : allAnnouncements.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 5,
overscan: 5,
debug: true,
});

useEffect(() => {
const [lastItem] = [...rowVirtualizer.getVirtualItems()].reverse();

if (!lastItem) {
return;
}

if (
lastItem.index >= allAnnouncements.length - 1 &&
hasNextPage &&
!isFetchingNextPage
) {
void fetchNextPage();
}
}, [
hasNextPage,
fetchNextPage,
allAnnouncements.length,
isFetchingNextPage,
rowVirtualizer.getVirtualItems(),
]);

return (
<>
{isLoading ? (
<AnnouncementSkeleton />
) : (
<div ref={parentRef}>
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
const isLoaderRow = virtualRow.index > allAnnouncements.length - 1;
const announcement = allAnnouncements[virtualRow.index];

return JSON.stringify(announcement);
})}
</div>
)}
{isFetching && !isFetchingNextPage ? <AnnouncementSkeleton /> : null}
</>
);
}
notrebekahmikaelson
screen recording of the issue with the detailed video explanation of the output showing console, tanstack router data and also my elements tab just another side note that console error is using forwardRef instead of using. that as regular props (probably used by radix-ui or shadcn)
app-index.js:33 Warning: Accessing element.ref is no longer supported. ref is now a regular prop. It will be removed from the JSX Element type in a future release.
app-index.js:33 Warning: Accessing element.ref is no longer supported. ref is now a regular prop. It will be removed from the JSX Element type in a future release.
update - when using JSON.strigify to wrap the entire ma[ping of row virtualizer , it renders them
Want results from more Discord servers?
Add your server