I have used react-window react-window package to implement virtualization and I am using <FixedSizeGrid>
component for that along with <InfiniteLoader>
from react-window-infinite-loader text.
But the problem is the loadMoreItems is not getting called. It is used properly as mentioned in its documentation. Also i have set limit=10 and threshold=5.
I tried implementing the infinite scroll
using react-window-infinite-loader package. but as the loadMoreItems is not getting called the Infinite-Scroll is not happening.
Expected behaviour : loadMoreItems should be called everytime threshold hits so that the Infinite-Scrolling can be possible.
Below is the code for the scenario discussed.
import { PropTypes } from 'prop-types';
import { FixedSizeGrid } from 'react-window';
import InfiniteLoader from 'react-window-infinite-loader';
import AutoSizer from 'react-virtualized-auto-sizer';
import './store_projects.scss';
import { useCallback } from 'react';
import useMediaQuery from '../../hooks/useMediaQuery';
import { StoreMediaQueries } from '../../constants';
const { mediaQueries } = StoreMediaQueries;
const VirtualizedInfiniteList = ({
items,
hasMore,
loadMoreItems,
threshold,
children,
isLoading,
}) => {
const activeMediaQuery = useMediaQuery(mediaQueries);
const { gridColumnCount = 1, gridRowHeight } = activeMediaQuery?.mediaQuery ?? {};
const isItemLoaded = (index) => !hasMore || index < items.length;
const loadMore = isLoading ? () => {} : loadMoreItems;
const getIndexFromGridPosition = useCallback((col, row, columnCount) => {
const index = (row * columnCount) + col;
return index;
}, []);
const itemCount = hasMore ? Math.ceil(items.length / gridColumnCount) + 1 : items.length;
return (
<AutoSizer>
{({ height, width }) => (
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMore}
threshold={threshold}
>
{({ onItemsRendered, ref }) => (
<FixedSizeGrid
className="virtualized-grid-wrapper"
columnCount={gridColumnCount}
columnWidth={width / gridColumnCount}
height={height}
ref={ref}
rowCount={Math.ceil(items.length / gridColumnCount)}
rowHeight={gridRowHeight}
width={width}
onItemsRendered={onItemsRendered}
>
{({ columnIndex, rowIndex, style }) => {
const index = getIndexFromGridPosition(columnIndex, rowIndex, gridColumnCount);
if (!items || items.length === 0 || index >= items.length) {
return null;
}
return (
<div className="store-project-card-wrapper" style={style}>
{children(items[index])}
</div>
);
}}
</FixedSizeGrid>
)}
</InfiniteLoader>
)}
</AutoSizer>
);
};
VirtualizedInfiniteList.propTypes = {
items: PropTypes.shape([]).isRequired,
hasMore: PropTypes.bool,
loadMoreItems: PropTypes.func,
threshold: PropTypes.number,
children: PropTypes.func.isRequired,
isLoading: PropTypes.bool,
};
VirtualizedInfiniteList.defaultProps = {
hasMore: false,
loadMoreItems: () => {},
threshold: 5,
isLoading: false,
};
export default VirtualizedInfiniteList;
LoadMoreItems function :
const loadMoreItems = useCallback(() => {
if (!isLoading && hasMore) {
setProject((prev) => ({ ...prev, isLoading: true }));
fetchMore({
variables: {
limit: allProjectsLimit,
offset: list.length,
},
updateQuery: (prev, { fetchMoreResult: { filterProjectsForAdmin: storeProjects } }) => {
if (!storeProjects.length) {
return prev;
}
setProject((prevProjects) => ({
list: [...prevProjects.list, ...storeProjects],
hasMore: storeProjects.length >= allProjectsLimit,
isLoading: false,
}));
return null;
},
});
}
}, [fetchMore, hasMore, isLoading, list.length]);
Ayush Bharadva is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.