I am not sure why this is happening but the InfiniteLoader
makes calls to fetch items twice(one for items from 0-8 and then from 8-16) when I am just loading the page and not scrolling at all. Also, even if I scroll only a couple of rows after 16 rows have been loaded, it triggers another call for 17-24.
Here's my container component..pretty similar to their code sandbox example
import React from 'react';
import PropTypes from 'prop-types';
import getPropType from '../../../common/js/proptypes';
import { connect } from 'react-redux';
import InfiniteList from 'src/common/components/InfiniteList';
import { fetchNextPage } from '../../state/reducers/training-slice';
import { bindActionCreators } from 'redux';
class Training extends React.Component {
render() {
const { hasNextPage, isNextPageLoading, trainings, fetchNextPage } = this.props;
return (
<>
<InfiniteList
hasNextPage={hasNextPage}
isNextPageLoading={isNextPageLoading}
items={trainings}
loadNextPage={fetchNextPage}
/>
</>
);
}
}
Training.propTypes = {
trainings: PropTypes.arrayOf(getPropType('training'))
};
const mapState = (state) => {
console.log(state.trainings);
return {
trainings: state.trainings.trainings,
isNextPageLoading: state.trainings.isFetching,
hasNextPage: state.trainings.trainings.length % state.trainings.limit === 0
};
};
const mapDispatch = (dispatch) => bindActionCreators({ fetchNextPage }, dispatch);
export default connect(mapState, mapDispatch)(Training);
the InfiniteList.js
component
import React from 'react';
import { FixedSizeList as List } from 'react-window';
import InfiniteLoader from 'react-window-infinite-loader';
export default function InfiniteList({ hasNextPage, isNextPageLoading, items, loadNextPage }) {
// If there are more items to be loaded then add an extra row to hold a loading indicator.
const itemCount = hasNextPage ? items.length + 1 : items.length;
const loadMoreItemsProxy = (start, end) => {
console.log(start, end);
loadNextPage();
};
// Only load 1 page of items at a time.
// Pass an empty callback to InfiniteLoader in case it asks us to load more than once.
const loadMoreItems = isNextPageLoading ? () => {} : loadMoreItemsProxy;
// Every row is loaded except for our loading indicator row.
const isItemLoaded = (index) => !hasNextPage || index < items.length;
// Render an item or a loading indicator.
const Item = ({ index, style }) => {
let content;
if (!isItemLoaded(index)) {
content = 'Loading...';
} else {
content = items[index].courseFullName;
}
return <div style={style}>{content}</div>;
};
return (
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMoreItemsProxy}
minimumBatchSize={8}
threshold={10}
>
{({ onItemsRendered, ref }) => (
<List
className="List"
height={150}
itemCount={itemCount}
itemSize={30}
onItemsRendered={onItemsRendered}
ref={ref}
width={300}
>
{Item}
</List>
)}
</InfiniteLoader>
);
}
and following is the output of state changes on the console which shows the call is being made twice to fetch a total of 16 items. what's going wrong here? I have tried different minimumBatchSize
and threshold
config but it doesn't seem to work.
Lower threshold values seem to prevent prefetch. I finally understood what threshold means - Just add "from the bottom" to the last sentence in the doc.
That means if you initially load 10 entries, and have a threshold of 2, the lib will fetch extra data as soon as the 8th(10 - 2) entry is in the viewport of the list(think IntersectionObserver API)
https://codesandbox.io/s/happy-bogdan-rd596c?file=/src/ExampleWrapper.js