How to stay in same scroll position when adding items to the top of a div?
Asked Answered
T

3

7

I want when the user scrolls from the bottom to the top of a div to load more items into that div to the top part of the div and I want to maintain the scroll position (or rather make sure the top item before adding more items is still visible after adding the items)

For example if I have item 100 on the top and 100 more items has been loaded into the div then I want item 100 to still be the focus of the scroll position, currently when I add items to the div it jumps to item 200...

I'd love to get help with this issue, thanks in advance :)

Terrorize answered 24/6, 2020 at 16:39 Comment(1)
get scroll offset before adding 100 items and set to it again after adding.. this is one way of logic. try to have simple sample and we can help to achive yoursPrincessprinceton
T
2

I found this answer useful, I just created the same logic but in React jquery - keep window from changing scroll position while prepending items to a list?

Terrorize answered 27/6, 2020 at 23:31 Comment(0)
C
1

You can watch the scrollHeight property of your scrollable area. When the items are prepended, the scrollHeight will increase. Then you can compute the diff of old_scrollHeight - scrollHeight. Finally, you scroll the element from top by that diff

// track the prev scrollHeight in state
const [scrollHeight, setScrollHeight] = useState(0);
    
useEffect(() => {
  const scrollableElement = scrollableRef.current;

  if (scrollableElement && scrollHeight != scrollableElement.scrollHeight) {
    const diff = scrollableElement.scrollHeight - scrollHeight;

    if (diff) {
      console.log({ diff });
      setTimeout(() => {
        scrollableElement.scrollTo({
          top: diff,
        });
      }, 0);
    }

    setScrollHeight(scrollableElement.scrollHeight);
  }

  console.log({ scrollHeight });
}, [scrollableRef, scrollHeight]);
Cloister answered 18/4, 2024 at 10:42 Comment(0)
S
0

I turned @Mist's answer into a hook. It's also necessary to pass the data as a dependency to the useEffect if it is loaded async. Otherwise, we don't store the scroll position when the data arrives.

import { useEffect, useState } from "react";

/**
 * Custom hook to maintain the scroll position of a scrollable container when the displayed data changes.
 *
 * @param scrollContainerRef - A reference to the scrollable container element.
 * @param data - The data displayed in the scrollable container. Typically, this is an array. When this data changes, the hook ensures the scroll position is maintained.
 *
 * @returns void
 */
export default function useMaintainScrollPosition(
  scrollContainerRef: React.RefObject<HTMLDivElement>,
  data: any
) {
  const [prevScrollHeight, setPrevScrollHeight] = useState(0);

  useEffect(() => {
    const scrollableElement = scrollContainerRef.current;

    if (
      scrollableElement &&
      prevScrollHeight != scrollableElement.scrollHeight
    ) {
      const diff = scrollableElement.scrollHeight - prevScrollHeight;

      if (diff) {
        console.log({ diff });
        setTimeout(() => {
          scrollableElement.scrollTo({
            top: diff,
          });
        }, 0);
      }

      setPrevScrollHeight(scrollableElement.scrollHeight);
    }
  }, [scrollContainerRef, prevScrollHeight, data]);
}
Schmo answered 8/10, 2024 at 9:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.