VirtualScroll (List) with dynamic item height scrolling not smooth and jumping
See original GitHub issueI have been tuning the VirtualScroll (List) component for almost whole day but no luck. I’m building a web based chatting application in which uses the react-virtualized List to display the chatting messages. Since message may have different content and different height, I use react-measure to calculate the item height and issue the recomputeRowHeights in rowRenderer.
The result is bad, VirtuallScroll List will jump around whenever I stopped the scrolling. For example, when I scrolled to the half of browser, I should see the middle of the messages, but it always suddenly shift the offset. Please take a look at the recorded video: https://drive.google.com/file/d/0B_W64UoqloIkcm9oQ08xS09Zc1k/view?usp=sharing
Since I only use the List and Autosizer component, I only adapt the required css file into my project which is like
.VirtualScroll {
width: 100%;
outline: none;
}
For the render method, I nested a lot of flex components inside the rowRender: Here is the code:
render() {
const inChat = this.context.store.getState().inChat;
const {conversationList} = this.state;
const imgUrl = 'img/builtin-wallpaper-1.jpg';
const backgroundStyle = {
backgroundImage: 'url(' + imgUrl + ')',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'top left'
};
// console.log('inChat');
// console.log(inChat);
if (inChat.id === this.id && inChat.status === 'FETCHING'){
return (
<Box column center height="80%">
<CircularProgress />
</Box>
);
} else if (inChat.id === this.id && inChat.status === 'FETCHED'){
return (
<Box column flex="1 0 100%" style={backgroundStyle}>
<HorizontalToolBar/>
<AutoSizer disableHeight={true}>
{({ width }) => (
<List
ref={(element) => {this.VirtualScroll = element;}}
className='VirtualScroll'
height={window.innerHeight - toolbarHeight - textAreaHeight}
overscanRowCount={10}
noRowsRenderer={this._noRowsRenderer.bind(this)}
rowCount={conversationList.length}
rowHeight={i => {
return (Measured_Heights[i.index] | 20); // default Height = 58
}}
rowRenderer={this._rowRenderer}
scrollToIndex={undefined} // scroll to latest item
width={width}
/>
)}
</AutoSizer>
<InputControl chatId={this.id} sendChatText={this._sendChatText.bind(this)}/>
</Box>
);
} else {
return null;
}
}
_rowRenderer ({ index, key, style, isScrolling }) {
console.log(Measured_Heights);
const rowData = this._getDatum(index);
// let renderItem;
// console.log('index = ' + index + ' key = ' + key);
if (rowData.type == 'conversation') {
if (rowData.data.type == netModule.TYPE_SYSTEM) {
// system message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<SystemMessage data={rowData.data}/>
</Measure>
)
}
if (rowData.data.senderId == this.state.selfProfile.username) {
// outgoing message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<RightMessage
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
} else {
// incoming message
// append userProfile to left messages
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<LeftMessage
userId={rowData.data.senderId}
userProfile={this.state.groupUserProfiles[rowData.data.senderId]}
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
}
}
}
I read a couple docs that Flexbox may be intercept the scrolling event, but even though I added overflow-y: hidden to nested component I didn’t see the issue disappear. Have you ever seen this wrong scrolling behavior with List component before? Any suggestion is welcome.
Issue Analytics
- State:
- Created 7 years ago
- Comments:19 (12 by maintainers)
Top GitHub Comments
@EllisShen I had a similar symptom when upgrading a VirtualScroll to List (8.x). Make sure you pass the
style
property in _rowRenderer() to the parent components it returns (and that the components render() the style)Docs are hard 😅 The more I write, the harder it is to find any given one.
I try to provide a simplified use-case/example with each component that shows its most basic functionality. In the case of
List
the example would be here. I think therowRenderer
in that example fills the role you’re describing?Either way~ I happily welcome contributions to make the docs more user-friendly. I’ve been working with this library so long that I sometimes lose touch with common questions for people just starting out with it.