Skip to main content

useScrollToOld

When you are using reverse InfiniteScroll, you may want to record the position before prepending the new data and then scroll to the original position after prepending the new data. useScrollToOld helps you to do this.

Parametersโ€‹

declare function useScrollToOld<T extends HTMLElement>(ref: React.RefObject<T>): [() => void, () => void];

refโ€‹

Rhe reference of your scrollable container.

Returnsโ€‹

scrollToOldโ€‹

The first value in the returned array is scrollToOld. It allow you to scroll to the original position.

note

If you didn't specify the old scroll position, then scrollToOld will scroll your scrollable container to the top.

recordScrollโ€‹

The second value in the returned array is recordScroll. Use recordScroll to record the original scroll position.

Exampleโ€‹

function ReverseExample() {
const [isLoading, setIsLoading] = useState(false);
const [page, setPage] = useState(1);
const [data, setData] = useState<Data[]>([]);
const containerRef = useRef<HTMLUListElement>(null);
const [scrollToOld, recordScroll] = useScrollToOld(containerRef);

const next = async () => {
setIsLoading(true);
const newData = await fakeApi(page);
const reverseData = [...newData].reverse();
recordScroll(); // record old scroll position
setData(oldData => [...reverseData, ...oldData]);
setPage(oldPage => oldPage + 1);
setIsLoading(false);
scrollToOld(); // scroll to old position
};

useEffect(() => {
fakeApi(0).then(initData => {
setData([...initData].reverse());
if (!containerRef.current) return;
const scrollTop = containerRef.current.scrollHeight - containerRef.current.clientHeight;
containerRef.current?.scrollTo({ top: scrollTop });
});
}, []);

return (
<ul ref={containerRef}>
<InfiniteScroll isLoading={isLoading} hasMore={true} next={next} threshold={1} reverse>
{data.map(datum => {
return (
<ListItem key={datum.id} title={datum.title} id={datum.id}>
<div>I am a JSX element</div>
</ListItem>
);
})}
</InfiniteScroll>
</ul>
);
}