Sint doloribus id voluptatem nulla dicta deserunt. Enim exercitationem aut modi saepe numquam ea. Voluptas mollitia non totam tempora delectus tenetur necessitatibus officiis. Odit vero consequatur qui dolorem et. Repellendus quia iure et dolorem.Similique molestiae id officia corporis quidem. Aliquam et ut eos ut nemo est voluptatem. Possimus ut quo labore. Alias amet quia enim. Quia ipsum pariatur facere illum esse recusandae veniam. Nihil enim fugit porro nam et quis sunt.Tempora id non maxime. Qui qui dignissimos omnis adipisci qui. Voluptatibus ut labore est quisquam consequuntur fugiat harum tenetur est. Repellendus quisquam quaerat error nobis voluptatem nihil minima. Autem aliquid ut adipisci officia eos atque excepturi.
import { useState, useRef, useCallback, memo } from "react";
import {
useVirtual,
useSubscription,
EVT_RANGE,
List
} from "@af-utils/react-virtual-list";
import useFakerSeed from "/hooks/useFakerSeed";
import { randNumber, randParagraph } from "@ngneat/falso";
const fetchRandomDescriptions = () =>
new Promise(resolve =>
setTimeout(
resolve,
200,
Array.from({ length: 5 }, () =>
randParagraph({ length: randNumber({ min: 1, max: 3 }) })
)
)
);
const Item = memo(({ i, model, data: posts }) => (
<div ref={el => model.el(i, el)} className="p-4">
<div className="border-4 text-center ring-inset leading-[30vh] bg-green-100">
some picture
</div>
<p>{posts[i]}</p>
</div>
));
const EVENTS = [EVT_RANGE];
const Posts = () => {
// fake data should be consistent for ssr purpose
useFakerSeed(12345);
const [posts, setPosts] = useState(() => [
randParagraph({ length: randNumber({ min: 1, max: 3 }) })
]);
const isLoadingRef = useRef(false);
const model = useVirtual({
itemCount: posts.length,
estimatedItemSize: 500
});
useSubscription(
model,
EVENTS,
useCallback(async () => {
if (isLoadingRef.current === false && posts.length === model.to) {
isLoadingRef.current = true;
const paragraphs = await fetchRandomDescriptions();
isLoadingRef.current = false;
setPosts(p => [...p, ...paragraphs]);
}
}, [model, posts])
);
return (
<List model={model} itemData={posts} className="h-full">
{Item}
</List>
);
};
export default Posts;
Virtual scroll model can emit EVT_RANGE
, which is very convenient for loading something on demand.
Here new posts are loaded when list is scrolled till the end, but this behavior can be easily customized.