VirtualScroll (список) с динамической прокруткой высоты элемента не плавно и скачкообразно

#react-virtualized

#реагировать виртуализировано

Вопрос:

Я настраивал компонент VirtualScroll (список) почти целый день, но безуспешно.

Я создаю веб-приложение для общения в чате, в котором для отображения сообщений в чате используется список виртуализированных реакций. Поскольку сообщение может иметь разное содержимое и разную высоту, я использую react-measure для вычисления высоты элемента и выдачи recomputeRowHeights в rowRenderer .

Результат плохой, список VirtuallScroll будет прыгать всякий раз, когда я останавливал прокрутку. Например, когда я прокручиваю половину браузера, я должен видеть середину сообщений, но это всегда внезапно смещает смещение. Пожалуйста, взгляните на записанное видео: https://drive.google.com/file/d/0B_W64UoqloIkcm9oQ08xS09Zc1k/view?usp=sharing

Поскольку я использую только компонент списка и автоопределения, я только адаптирую требуемый файл css в свой проект, который выглядит как «

 .VirtualScroll {
    width: 100%;
    outline: none;
}
  

«`

Для метода рендеринга я вложил много гибких компонентов внутри rowRender: вот код:

«`

 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'
    };

    if (inChat.id === this.id amp;amp; inChat.status === 'FETCHING'){
        return (
                <Box column center height="80%">
                    <CircularProgress />
                </Box>
        );
    } else if (inChat.id === this.id amp;amp; 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>
            );
        }
    }
}
  

«`

Я прочитал пару документов о том, что Flexbox может перехватывать событие прокрутки, но, несмотря на то, что я добавил overflow-y: hidden во вложенный компонент, я не видел, чтобы проблема исчезла. Вы когда-нибудь видели это неправильное поведение прокрутки с компонентом списка раньше?

Любое предложение приветствуется.

Ответ №1:

Я не вижу видео, но я думаю, что у меня было что-то подобное в последнее время. Из того, что я вижу, вы не используете style параметр, переданный в ваш _rowRenderer метод. Этот параметр содержит некоторые преобразования CSS, которые заставляют строку отображаться в правильном вертикальном положении в списке прокрутки.