Try this:
- I created a
DataScroller
component that takes the data and a size i.e. 15
- I modified the
arr
variabel in utils
to dynamically generate 120 records
fetchMoreData
is now a callback
- There is an effect to set
hasMore
upon data changes
Note: I updated react-infinite-scroll-component
to 6.1.0
(latest version available as of this post). I was getting a lot of Warning with the version you were using.
App.js
import DataScroller from "./DataScroller";
import { arr } from "./utils";
export default function App() {
return (
<>
<div className="mt-24"></div>
<DataScroller data={arr} size={15} />
</>
);
}
DataScroller.js
import { useCallback, useEffect, useState } from "react";
import InfiniteScroll from "react-infinite-scroll-component";
export default function DataScroller({ data, size }) {
const [hasMore, setHasMore] = useState(data.length > size);
const [visibleData, setVisible] = useState(data.slice(0, size));
const fetchMoreData = useCallback(() => {
setTimeout(() => {
setVisible((currentData) => {
const startIndex = currentData.length;
const endIndex = Math.min(startIndex + size, data.length);
return structuredClone(currentData).concat(
data.slice(startIndex, endIndex)
);
});
}, 1000);
}, [data, size]);
useEffect(() => {
setHasMore(visibleData.length < data.length);
}, [data, visibleData]);
return (
<InfiniteScroll
dataLength={visibleData.length}
next={fetchMoreData}
hasMore={hasMore}
loader={<h3 className="font-bold text-2xl">Loading...</h3>}
endMessage={
<p className="text-base my-4 font-medium text-center">
<b>Yay! You have seen it all</b>
</p>
}
>
{visibleData.map((t) => (
<li key={t.id} className="mx-4 mt-8">
{" "}
{t.name.concat(` ${t.id}`)}
</li>
))}
</InfiniteScroll>
);
}
utils.js
export const arr = Array.from({ length: 120 }, (_, i) => ({
id: i + 1,
name: "div"
}));