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 :)
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 :)
Share Improve this question asked Jun 24, 2020 at 16:39 123123 1974 silver badges19 bronze badges 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 yours – Uthistran Selvaraj Commented Jun 24, 2020 at 16:41
3 Answers
Reset to default 2I 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?
You can watch the scrollHeight
property of your scrollable area.
When the items are prepended, the scrollHeight
will increase.
Then you can pute 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]);
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]);
}