6

I have a fixed list and grid using react-window, infinite loader, and auto sizer. It's working fine but I'm looking to append a component before the list/grid starts (for example, a search box and a button). What's the correct approach to accomplish this? I want this component to scroll with the fixed list and not scroll separately. I've tired just rendering the component before but then it's not in the fixed list container and doesn't scroll with it.

{/* WANT TO ADD SOME SORT OF COMPONENT HERE SO IT CAN SCROLL WITH LIST */}
{/* CAN'T IN HERE BECAUSE ITS NOT INSIDE THE FIXED CONTAINER SO IT SCROllS SEPARATELY */}
<AutoSizer>
    {({ height, width }) => (
        <InfiniteLoader
            isItemLoaded={index => index < stateData.data.length}
            itemCount={stateData.data.length + 1}
            loadMoreItems={loadMoreProducts}
        >
            {({ onItemsRendered, ref }) => (
                <FixedSizeList
                    onItemsRendered={onItemsRendered}
                    ref={ref}
                    height={height}
                    itemCount={stateData.data.length + 1}
                    itemSize={350}
                    width={width}
                >
                    {/* WANT TO ADD SOME SORT OF COMPONENT HERE SO IT CAN SCROLL WITH LIST */}
                    {/* CAN'T IN HERE BECAUSE ITS LOOPING LISTITEM */}
                    {ListItem}
                </FixedSizeList>
            )}
        </InfiniteLoader>
    )}
</AutoSizer>

Edit: Pretty much I don't want the list (or grid) and the actual page to be two different scroll containers. I'd like the whole page to scroll together. I've come across this issue because some of my containers need to have an infinite list of items users can scroll through so the list needed to be virtualized to improve performance.

See a demo here. Really the fixed container should just be considered the whole page and the search box and everything else should scroll with the infinite list. Having two different scroll containers isn't too great for the ux.

SeanWM
  • 16,789
  • 7
  • 51
  • 83

2 Answers2

0

If you want the whole page to scroll with your virtual list you will need a window scroller. This also involves playing around with some styling as well. To make your searchbox scroll with your list you will need a position of fixed. A spacer div and some styling helps the illusion.

I added a basic window scroller and some styling changes to your codepen here.

apachuilo
  • 341
  • 3
  • 6
0

A few options:

  • Make a wrapper around The autosizer, that holds both your search box and the autosizer.
<>
  <SearchBox />
  <AutoSizer>
    ... your items
  </AutoSizer>
</>
  • let the AutoSizer contain both the search and the list
<AutoSizer>
  <SearchBox />
  <List>
    ... your items
  </List>
</AutoSizer>
  • Since your infinite scroll is using a render function you might need fragments
<AutoSizer>
  <InfiniteScroll>
    {({ onItemsRendered, ref }) => (
      <>
        <SearchBox />
        <List>
          ... your items
        </List>
      <>
    )}
  </InfiniteScroll>
</AutoSizer>

Here I edited your example and made it work using this approach.

Please note that the page scrolls only because of the top and bottom bars; which is the behaviour in your example.

  • Let the infinite loader populate an array, and append an extra item to that. The item can have a certain type. Assuming the FixedSizeList is the List component from react-virtualized then you can use it's rowRenderer to render the item of type "search" differently than the other items. Something like:
function rowRenderer ({ key, type, value, ...rest }) {
  if (type === 'search') {
    return <Search key={key} placeholder={value} {...rest} />
  } 

  return <div key={key} {...rest}>{value}</div>
}

// Render your list
ReactDOM.render(
  <AutoSizer>
    {({ height, width }) => (
      <List
        height={height}
        rowCount={list.length}
        rowHeight={20}
        rowRenderer={rowRenderer}
        width={width}
      />
    )}
  </AutoSizer>,
  document.getElementById('example')
);

Perhaps it also helps to look at the simple example from Vaughn.

Webber
  • 4,672
  • 4
  • 29
  • 38