<!DOCTYPE html>
<html>
  <head>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-virtualized/dist/umd/react-virtualized.js"></script>

    <link rel="stylesheet" href="https://unpkg.com/react-virtualized/styles.css">
    <link rel="stylesheet" href="styles.css">
  </head>

  <body>
    <div id="example">
      <!-- This element's contents will be replaced with your code... -->
    </div>
    <script src="script.js"></script>
  </body>

</html>
var List = ReactVirtualized.List;
var InfiniteLoader = ReactVirtualized.InfiniteLoader;
var AutoSizer = ReactVirtualized.AutoSizer;
var WindowScroller = ReactVirtualized.WindowScroller;
var CellMeasurer = ReactVirtualized.CellMeasurer;
var CellMeasurerCache = ReactVirtualized.CellMeasurerCache;

var pageKey = 0;
var apiList = Array.from(
  { length: 100 },
  (_, i) => ({
    displayName: `li-${i}`,
    imageSource: i === 12 
      ? 'https://images.anandtech.com/doci/9853/RTG_Software%20Session_FINAL-page-023.jpg'
      : 'https://pbs.twimg.com/profile_images/699768459522154496/y3ILwo06_400x400.png'
  })
);
var list = [];
var _isRowLoaded = ({ index }) => !!list[index];
var _loadMoreRows = () => {
  list = list.concat(apiList.slice(pageKey, mockNextPageKeyFromAPI()))
  console.log(list.length)
  return Promise.resolve();
}
var cache = new CellMeasurerCache({
  defaultHeight: 30,
  fixedWidth: true
});
var _rowRenderer = ({ index, isScrolling, key, parent, style }) => (
  <CellMeasurer
    cache={cache}
    columnIndex={0}
    rowIndex={index}
    {...{ key, parent }}
  >
    {({ measure }) =>
      <div
        className='Row'
        style={style}
        key={key}
      >
        {
          !list[index]
            ? 'loading'
            : (
              <ListItem
                displayName={list[index].displayName}
                imageSource={list[index].imageSource}
                measure={measure}
              />
            )
        }
      </div>
    }
  </CellMeasurer>
);


var app = (
  <div style={{ display: 'flex', height: '100vh', width: '60%' }}>
    <div style={{ flex: '1 1 auto' }}>
      <InfiniteLoader
        isRowLoaded={_isRowLoaded}
        loadMoreRows={_loadMoreRows}
        rowCount={apiList.length}
      >
        {({ onRowsRendered, registerChild }) => 
          <WindowScroller>
            {({ height, isScrolling, scrollTop }) => 
              <AutoSizer disableHeight>
                {({ width }) => 
                  <List
                    className='List'
                    ref={registerChild}
                    width={width}
                    height={height}
                    autoHeight
                    rowCount={apiList.length}
                    deferredMeasurementCache={cache}
                    rowHeight={cache.rowHeight}
                    onRowsRendered={onRowsRendered}
                    rowRenderer={_rowRenderer}
                    scrollTop={scrollTop}
                  />
                }
              </AutoSizer>
            }
          </WindowScroller>  
        }
      </InfiniteLoader>
    </div>
  </div>
);

ReactDOM.render(app, document.getElementById('example'));

function mockNextPageKeyFromAPI() {
  pageKey = pageKey + 30;
  return pageKey;
}

function ListItem({ displayName, imageSource, measure }) {
  return (
    <div>
      {displayName}
      <img 
        onLoad={measure}
        src={imageSource}
      />
    </div>
  )
}
.List {
  border: 1px solid black;
  box-sizing: border-box;
}
.Row {
  width: 100%;
  height: 100%;
  border-bottom: 1px solid black;
  display: flex;
  align-items: center;
  padding: 0 0.5rem;
  box-sizing: border-box;
}