react-infinite-scroll-component icon indicating copy to clipboard operation
react-infinite-scroll-component copied to clipboard

fetching new item send the scrollbar to the top

Open spbo opened this issue 5 years ago • 6 comments

Hello, When I fetch my next data, the scrollbar is going back to the top and not stay in the last item and continue from there. I follow the same concept as the first demo provided in readme.md.

Here's the sandbox with the problem. Is there something perhaps I missed?

spbo avatar Dec 08 '20 12:12 spbo

hi did you resolve this problem i met the same as yours

lixiaohulee avatar Jan 08 '21 03:01 lixiaohulee

hi did you resolve this problem i met the same as yours

Hi! Unfortunately, I haven't.

spbo avatar Jan 08 '21 08:01 spbo

I've just found a great workaround for this. Here's a small example taken from my working code. Note that this is an example using inverse scrolling (a chat app).

  • chatScrollDiv is a useRef'd div (also the "scrollableDiv")
  • loadMoreMessages is an action creator (updates the store with more elements for the InfiniteScroll) which returns a promise on completion. Before I used the promise, it worked but it took some time before it jerked to the right position. Now it doesn't move at all and looks perfect.
  • loadMoreMessagesHelper is the InfiniteScroll's next function
  const [prevScrollHeight, SetPrevScrollHeight] = useState(0);
  useEffect(() => {
    if (!chatScrollDiv.current) return;
    // Can't just have this after the chatScrollDiv.current.scrollTo because
    //  it needs to be set before the first load, to update again after a
    //  different conv is loaded, etc.
    SetPrevScrollHeight(chatScrollDiv.current.scrollHeight);
  }, [chatScrollDiv.current, current_conversation]);

  const loadMoreMessagesHelper = () => {
    loadMoreMessages(
      current_conversation._id,
      current_conversation.loaded_messages
    ).then(() => {
      if (!chatScrollDiv.current) return;
      const targetScroll =
        chatScrollDiv.current.scrollHeight - prevScrollHeight;

      chatScrollDiv.current.scrollTo(0, targetScroll);
    });
  };

Hope this helps.

abookout avatar Feb 24 '21 19:02 abookout

Here's the sandbox with the problem. Is there something perhaps I missed?

The problem is in returned order and isLoading variable. When you fetch next page, isLoading = true and return only 'Loading...' text from component so the data is not displaying at this moment that is why the height of the page does not contain scroll.

You can fix it by changing the order of the returning:

  if (data) {
    return ...
  };
  if (isLoading) return "Loading...";
  if (error) return `Something went wrong: ${error.message}`;

But in this case the loading and error messages could be displayed only once, so you need to put them into if (data) {...} too.

MsSterh avatar May 18 '21 09:05 MsSterh

hi did you resolve this problem i met the same as yours

I had the same problem, but in my case the problem was in autoFocus. Input field contained auto focus that sent the scrollbar to the top after updating the data.

MsSterh avatar May 18 '21 09:05 MsSterh

I've just found a great workaround for this. Here's a small example taken from my working code. Note that this is an example using inverse scrolling (a chat app).

  • chatScrollDiv is a useRef'd div (also the "scrollableDiv")
  • loadMoreMessages is an action creator (updates the store with more elements for the InfiniteScroll) which returns a promise on completion. Before I used the promise, it worked but it took some time before it jerked to the right position. Now it doesn't move at all and looks perfect.
  • loadMoreMessagesHelper is the InfiniteScroll's next function
  const [prevScrollHeight, SetPrevScrollHeight] = useState(0);
  useEffect(() => {
    if (!chatScrollDiv.current) return;
    // Can't just have this after the chatScrollDiv.current.scrollTo because
    //  it needs to be set before the first load, to update again after a
    //  different conv is loaded, etc.
    SetPrevScrollHeight(chatScrollDiv.current.scrollHeight);
  }, [chatScrollDiv.current, current_conversation]);

  const loadMoreMessagesHelper = () => {
    loadMoreMessages(
      current_conversation._id,
      current_conversation.loaded_messages
    ).then(() => {
      if (!chatScrollDiv.current) return;
      const targetScroll =
        chatScrollDiv.current.scrollHeight - prevScrollHeight;

      chatScrollDiv.current.scrollTo(0, targetScroll);
    });
  };

Hope this helps.

can you help me example in codesandbox please ??

tanhsnkt1997 avatar Jul 07 '21 15:07 tanhsnkt1997