javascriptreactjsreact-virtualizedreact-window

react-window-infinite-loader prefetching extra data


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.

enter image description here


Solution

  • 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.

    enter image description here

    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