React-window: [react-window-infinite-loader] Can't call resetAfterIndex() on child VariableSizeList, because of ref;

Created on 9 Feb 2020  Â·  2Comments  Â·  Source: bvaughn/react-window

Hello, is there a way to call resetAfterIndex() on a child VariableSizeList, inside InfiniteLoader?

The ref that comes from InfiniteLoader is a function:

function _setRef() {
  length: 1
  ​name: ""
  ​prototype: Object { … }
  ​<prototype>: function ()

My current "solution" is to use my own ref, instead of the one from InfiniteLoader

<InfiniteLoader isItemLoaded={isItemLoaded} itemCount={1000} loadMoreItems={loadMoreItems}>
    {({ onItemsRendered }) => {
      return <VariableSizeListWrapper onItemsRendered={onItemsRendered} />;
    }}
</InfiniteLoader>

and inside the VariableSizeListWrapper

const ref = React.useRef();
...
React.useEffect(() => {
    if (ref?.current) {
      ref.current.resetAfterIndex(0);
    }
  }, [someCollection]);
...
<VariableSizeList ref={ref} ...
....

Everything seems to be working - loading more elements, itemSize is updated, when items are added or re-ordered, etc, but I get this warning: Invalid list ref; please refer to InfiniteLoader documentation.

Looking at dist/index.esm.js, it might be messing up with "_loadUnloadedRanges", but I haven't noticed anything.

Most helpful comment

The solution here is to use a "callback ref" to get a handle on the VariableSizeList ref, then pass that on to InfiniteLoader too.

const yourRef = useRef(null);

<InfiniteLoader {...props}>
  {({ onItemsRendered, ref }) => (
    <List
      ref={list => {
        // Pass List ref through to InfiniteLoader
        ref(list);

        // And store a copy for yourself.
        yourRef.current = list;
      }}
      {...props}
    />
  )}
</InfiniteLoader>;

All 2 comments

The solution here is to use a "callback ref" to get a handle on the VariableSizeList ref, then pass that on to InfiniteLoader too.

const yourRef = useRef(null);

<InfiniteLoader {...props}>
  {({ onItemsRendered, ref }) => (
    <List
      ref={list => {
        // Pass List ref through to InfiniteLoader
        ref(list);

        // And store a copy for yourself.
        yourRef.current = list;
      }}
      {...props}
    />
  )}
</InfiniteLoader>;

Had the same issue. @bvaughn, thank you for the solution.

React-window is a great small performant lib. It works very well. But in a case requiring lazy loading of images (actual dispatching of the GET request when each item comes into view), this window-scrolling isn't efficient at all. Few issues that emerge definitely when scrolling fast, or back up and down again:

  • GET requests get triggered for each image even if previously fetched. Thus, putting a hefty load computationally and at the backend. If not using CDN, good luck with the huge bill waiting!
  • Data leakage during unmounting of item moved out of view. This is due to ajax/ async operation happening in useEffect/ componentDidMount and not finishing when item gets unmounted on rapid scrolling. Hence, a need for complex logic to take care of this
  • If using a state to capture already fetched images, a problem arises when setting state is async and doesn't put images in FIFO order.

Therefore, I'd love to have the software legends here add a feature to nicely combine image lazy-loading with react-window :)

Was this page helpful?
0 / 5 - 0 ratings