Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop with Reversed Vertical list #36

Open
Aniket-IN opened this issue Apr 18, 2023 · 2 comments
Open

Infinite loop with Reversed Vertical list #36

Aniket-IN opened this issue Apr 18, 2023 · 2 comments
Labels
question Further information is requested

Comments

@Aniket-IN
Copy link

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>
  );
};
@onderonur onderonur added the question Further information is requested label Apr 20, 2023
@onderonur
Copy link
Owner

onderonur commented Apr 20, 2023

Hello there 👋

Thanks for your intereset to this package and also for this issue 🙏

If I understood the problem correctly, you need to handle the scroll position.

If you go to the demo and select Reversed Vertically Scrollable List for "List Type", you can see the behavior is similar to what would be expected from a chat.

The code for that component is here.

Basically, you need an useEffect which will update the scroll position after the new items are loaded and an onScroll handler to keep track of the current scroll position. And don't forget to set both scrollableRootRef and infiniteRef by using a useCallback (like here) to prevent any performance issues.

I think you will get it when you see the code 😄

And I see that these examples are a little scattered all around and people may miss them. So I'm planning to add these to the README.md or update the demo site to be more explicit.

I hope this helps you to solve the problem. If you have any further questions or if this answer solves the problem, please comment 🙏

I'll keep this issue open until I improve the documentation of these examples.

Thanks 🎉

@SeanRoberts
Copy link

For anyone finding this the layout of the repo has changed and the updated link to the example code is here: https://github.com/onderonur/react-infinite-scroll-hook/blob/main/apps/demo/src/components/infinite-list-with-reverse-vertical-scroll.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants