最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - How to avoid infinite scroll loops in a table? - Stack Overflow

programmeradmin8浏览0评论

I'm working on a React project using Tanstack Table to manage the state of the table and Tanstack query to manage the fetching of data from the server.

In my query, I load every 10 emails at a time, as the table scrolls down.

that's my logic:

  const lastElementOnTableRef = useRef<HTMLTableRowElement | null>(null);
  const lastElementOnCardRef = useRef(null);

As the app is responsive, I have a table ref (for desktops) and a card ref (for mobile), and depending on the screen size I apply a hidden css class to hide them.

Since the problem is only with the table, I'll show it to you and focus only on it.

I use the shadcn table:

 <Table>
            <TableCaption>Emails enviados</TableCaption>
            <TableHeader className="sticky top-0 bg-white">
              <TableRow>
                <TableHead>Assunto</TableHead>
                <TableHead>Destinatários</TableHead>
                <TableHead>Data do evento</TableHead>
                <TableHead>Enviado</TableHead>
                <TableHead>Anexo</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {emails?.map(({ ref, subject, recipients, sentDate, status, hasAttachment, body }, index) => (
                <TableRow
                  ref={index === emails.length - 1 ? lastElementOnTableRef : undefined}
                  key={ref.id}
    Rest of JSX not important...

Note that in the last element of the table, depending on the number of emails loaded, I apply the observer ref to it.

And here's my logic for observing the content and loading more, using the intersection observer API, to check the intersection:

  useEffect(() => {
    if (!hasNextEmailsList || isFetchingNextEmails) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) fetchNextEmailsList();
      },
      { threshold: 1 }
    );

    const lastElementOnTable = lastElementOnTableRef.current;
    const lastElementOnCard = lastElementOnCardRef.current;

    if (lastElementOnTable) observer.observe(lastElementOnTable);
    if (lastElementOnCard) observer.observe(lastElementOnCard);

    return () => {
      if (lastElementOnTable) observer.unobserve(lastElementOnTable);
      if (lastElementOnCard) observer.unobserve(lastElementOnCard);
    };
  }, [fetchNextEmailsList, hasNextEmailsList, isFetchingNextEmails, emails]);

When I scroll down the table normally, it works ok, finding the last one, intersecting it and loading 10 more.

However, if I hold down the scroll button at the end of the table, it loads emails every 10 minutes until the list runs out, the scroll should load 10 and adjust itself, but it doesn't if I keep holding it down.

Example: Always holding it at the end:

How to resolve this?

My infinite query:

async function fetchEmailsByContractId({ contractId, pageParam, isUserAdmin }: IEmailsFetchParams) {
  const emailsSentRef = collection(firestore, 'emailsSent').withConverter(EmailConverter);

  const contractFilter = where('contract', '==', contractId);
  const userUidFilter = where('userUid', '==', auth.currentUser?.uid);
  const queryFilters = isUserAdmin ? [contractFilter] : [contractFilter, userUidFilter];

  const baseQueryConstraints = [...queryFilters, limit(10), orderBy('createdAt', 'desc')];
  const queryContraints = pageParam ? [...baseQueryConstraints, startAfter(pageParam)] : baseQueryConstraints;

  const filteredDocs = query(emailsSentRef, ...queryContraints);
  const sentEmailsSnapshot = await getDocs(filteredDocs);

  return sentEmailsSnapshot.docs.map((doc) => ({
    ref: doc,
    ...doc.data(),
  }));
}

export function useFetchEmailsQuery(isUserAdmin: boolean) {
  const { contractId } = useContractIdStore();

  return useInfiniteQuery({
    queryKey: [...LIST_EMAILS_QUERY_KEY, contractId],
    queryFn: async ({ pageParam }) => fetchEmailsByContractId({ contractId, pageParam, isUserAdmin }),
    initialPageParam: undefined as QueryDocumentSnapshot | undefined,
    getNextPageParam: (lastPage) => lastPage[lastPage.length - 1]?.ref,
    select: (data) => data?.pages.flat(),
    enabled: !!contractId,
  });
}
发布评论

评论列表(0)

  1. 暂无评论