Skip to content

Infinite loop with Reversed Vertical list  #36

@Aniket-IN

Description

@Aniket-IN

Hi,

First of all thank you so much for the amazing package,
I'm trying to implement it with react-query for a chat application.

Basically, we need to first load most recent messages and when user scrolls to the top of the container, we load old messages.
Just like whatsapp.

I got the load on scroll working and everything is fine.

Just having one small issue:
What happens is on the Initial data load by react-query the container's scroll position is at the top.
And our sentryRef element is also on the top, that triggers loadMore and after loading more still the scroll position stays at top and it just keeps loading more and more, until all the data is loaded.

could you please provide a solution to this problem 😢.

Thank you.

Here's the code:

const ChatBox = ({ thread }: ChatBoxProps) => {
  const { axios } = useAxios();

  const fetchMessages = async ({ pageParam = 0 }) => {
    const response = await axios.get(
      `/api/v1/message-threads/${thread.id}/messages`,
      {
        params: {
          page_size: 10,
          pagination_mode: "cursor",
          cursor: pageParam,
          sort_field: "created_at",
          sort_direction: "desc",
        },
      }
    );

    return response.data;
  };

  const {
    isSuccess,
    data,
    isFetching,
    isFetchingNextPage,
    fetchNextPage,
    hasNextPage,
    isError,
  } = useInfiniteQuery<MessagesResponse>({
    queryKey: ["messages"],
    queryFn: fetchMessages,
    select: (data) => {
      return {
        pages: [...data.pages].reverse(),
        pageParams: [...data.pageParams].reverse(),
      };
    },
    getNextPageParam: (lastPage, pages) => lastPage.next_cursor,
  });

  const [sentryRef, { rootRef }] = useInfiniteScroll({
    loading: isFetching,
    hasNextPage: !!hasNextPage,
    onLoadMore: () => fetchNextPage(),
    disabled: isError,
    rootMargin: "0px 0px 0px 0px",
  });

  return (
    <div className="flex flex-grow flex-col divide-y border-b bg-white">
      <ChatHeader thread={thread} />

      {/* Chat Messages */}
      <div
        ref={rootRef}
        className="bg-accent h-0 flex-auto flex-col space-y-3 overflow-auto px-4"
      >
        {isSuccess && (isFetchingNextPage || hasNextPage) && (
          <div ref={sentryRef} className="py-3 text-center text-slate-500">
            Loading old chats...
          </div>
        )}

        {data?.pages.map((group, i) => (
          <Fragment key={i}>
            {[...group.data].reverse().map((message) => (
              <MessageBubble
                key={message.id}
                message={message}
                direction={
                  thread.contact_phone_number == message.from
                    ? "inbound"
                    : "outbound"
                }
              />
            ))}
          </Fragment>
        ))}
      </div>

      <MessageSender />
    </div>
  );
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions