When I'm trying to render multiple lists (2 in my case) after each other, both using <AutoSizer> and <WindowScroller>, the second one does not render properly. It takes up the correct amount of space on the page, but the rows are gone except for a few at the bottom of the page. If you scroll up, a few more of them appears. This issue does not happen after resizing your window, or if you set the width of your <List> component to a static value.
See codesandbox example.
@apelsinet, did you make any progress on this? I'm dealing with the same problem right now. I've noticed though that it does seem to work after once resizing the window. 馃

I was having this issue on a project, and I ended up putting everything inside a single and created a function to handle the height of everything, instead of having to use multiple autosizers and lists
Nope, I ended up not using virtualised lists on pages with multiple lists unfortunately.
I've done some more digging. I'm not familiar at all with the codebase, but maybe my findings still help:
WindowScroller has an updatePosition() method which measures the dom element's offset and stores it in _positionFromTop and _positionFromLeft. updatePosition() is called in componentDidMount(), but at the time the offsets are stored, the lists themselves haven't been painted yet. For the first one, that isn't a problem because _positionFromTop is correct no matter its height. But the second list does depend on what has been rendered above. So what seems to be happening is that an incorrect _positionFromTop is stored during the initial render, breaking virtualization in the second list. Resizing the window triggers updatePosition() to be called again from _onResize(), which fixes the incorrect offsets - hence the behavior demonstrated in my comment above.
Another place where updatePosition() is called is in registerChild. A (rather unsatisfying) quick fix for the problem seems to be doing something like this:
<WindowScroller>
{({ height, registerChild, scrollTop }) => (
<div>
<AutoSizer disableHeight>
{({ width }) => (
<div ref={el => registerChild(el)}> // <-- relevant line
<List
autoHeight
height={height}
rowCount={list1.length}
rowHeight={32}
rowRenderer={rowRenderer1}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
Note that it only works when recreating the function passed to ref on every render, i.e. ref={el => registerChild(el)} instead of ref={registerChild}. I've tweaked @apelsinet's example accordingly: https://codesandbox.io/s/jjnr1v3r3w?fontsize=14
It's obviously a hack and probably not the right long-term solution. I'm not sure at all about possible negative implications.
But at least it seems like RV isn't very far from supporting this use case. :)
@nicolasschabram thank you so much for doing the research and supplying this solution! It's definitely better than not using RV at all 馃槃
One more workaround that seems to work: wrapping the WindowScrollers in <div style={{height: rowCount * rowHeight}}>. Obviously that works only with fixed-height rows.
@nicolasschabram Thank you so much for this. Hack or not, it works for my use case without any apparent implications.
Most helpful comment
I've done some more digging. I'm not familiar at all with the codebase, but maybe my findings still help:
WindowScrollerhas anupdatePosition()method which measures the dom element's offset and stores it in_positionFromTopand_positionFromLeft.updatePosition()is called incomponentDidMount(), but at the time the offsets are stored, the lists themselves haven't been painted yet. For the first one, that isn't a problem because_positionFromTopis correct no matter its height. But the second list does depend on what has been rendered above. So what seems to be happening is that an incorrect_positionFromTopis stored during the initial render, breaking virtualization in the second list. Resizing the window triggersupdatePosition()to be called again from_onResize(), which fixes the incorrect offsets - hence the behavior demonstrated in my comment above.Another place where
updatePosition()is called is inregisterChild. A (rather unsatisfying) quick fix for the problem seems to be doing something like this:Note that it only works when recreating the function passed to
refon every render, i.e.ref={el => registerChild(el)}instead ofref={registerChild}. I've tweaked @apelsinet's example accordingly: https://codesandbox.io/s/jjnr1v3r3w?fontsize=14It's obviously a hack and probably not the right long-term solution. I'm not sure at all about possible negative implications.
But at least it seems like RV isn't very far from supporting this use case. :)