【问题标题】:react-virtualized - how do I use this as a true infinite scrollerreact-virtualized - 我如何将其用作真正的无限滚动器
【发布时间】:2018-01-06 12:34:52
【问题描述】:

我找不到任何可以回答这个问题的代码示例或文档:

  • 实现几乎完全的无限滚动 -> 项目数未知,但有一个有限的数量可能无法预先计算 - 例如在某些时候列表需要停止滚动
  • 我可以从 InfiniteScroller/List 中触发第一次数据加载吗?您似乎需要传入一个填充了初始页面的数据源

我正在使用这个例子: https://github.com/bvaughn/react-virtualized/blob/master/docs/creatingAnInfiniteLoadingList.md

和: https://github.com/bvaughn/react-virtualized/blob/master/source/InfiniteLoader/InfiniteLoader.example.js

与 CellMeasurer 一起用于动态高度: https://github.com/bvaughn/react-virtualized/blob/master/source/CellMeasurer/CellMeasurer.DynamicHeightList.example.js

InfiniteLoader.rowCount 的文档说: "列表中的行数;如果实际数量未知,则可以是任意大数。"

那么你如何表明没有更多的行了。

如果有人可以发布使用 setTimeout() 模拟动态加载数据的示例,谢谢。我可以让 CellMeasurer 从那里开始工作。

编辑

这并不像 react-virtualized creator 所说的那样或无限加载示例所暗示的那样工作。

来电:

  • render(): rowCount = 1
  • _rowRenderer(index = 0)
  • _isRowLoaded(index = 0)
  • _loadMoreRows(startIndex = 0, stopIndex = 0)
  • _rowRenderer(index = 0)
  • 结束

我需要指定批量大小或其他一些属性吗?

class HistoryBrowser extends React.Component
{
    constructor(props,context,updater)
    {
        super(props,context,updater);
        this.eventEmitter = new EventEmitter();
        this.eventEmitter.extend(this);
        this.state = {
            history: []
        };
        this._cache = new Infinite.CellMeasurerCache({
            fixedWidth: true,
            minHeight: 50
        });
        this._timeoutIdMap = {};
        _.bindAll(this,'_isRowLoaded','_loadMoreRows','_rowRenderer');

    }


    render()
    {
        let rowCount = this.state.history.length ? (this.state.history.length + 1) : 1;
        return <Infinite.InfiniteLoader
            isRowLoaded={this._isRowLoaded}
            loadMoreRows={this._loadMoreRows}
            rowCount={rowCount}
        >
            {({ onRowsRendered, registerChild }) =>
                <Infinite.AutoSizer disableHeight>
                    {({ width }) =>
                        <Infinite.List
                            ref={registerChild}
                            deferredMeasurementCache={this._cache}
                            height={200}
                            onRowsRendered={onRowsRendered}
                            rowCount={rowCount}
                            rowHeight={this._cache.rowHeight}
                            rowRenderer={this._rowRenderer}
                            width={width}
                        />}
                </Infinite.AutoSizer>}
        </Infinite.InfiniteLoader>
    }

    _isRowLoaded({ index }) {
        if (index == 0 && !this.state.history.length)
            // No data yet, force load
            return false;
    }

    _loadMoreRows({ startIndex, stopIndex }) {
        let self = this;
        for (let i = startIndex; i <= stopIndex; i++) {
            this.state.history[startIndex] = {loading: true};
        }

        const timeoutId = setTimeout(() => {
            delete this._timeoutIdMap[timeoutId];

            for (let i = startIndex; i <= stopIndex; i++) {
                self.state.history[i] = {loading: false, text: 'Hi ' + i };
            }

            promiseResolver();
        }, 10000);

        this._timeoutIdMap[timeoutId] = true;

        let promiseResolver;

        return new Promise(resolve => {
            promiseResolver = resolve;
        });
    }

    _rowRenderer({ index, key, style }) {
        let content;
        if (index >= this.state.history.length)
            return <div>Placeholder</div>
        else if (this.state.history[index].loading) {
            content = <div>Loading</div>;
        } else {
            content = (
                <div>Loaded</div>
            );
        }

        return (
            <Infinite.CellMeasurer
                cache={this._cache}
                columnIndex={0}
                key={key}
                rowIndex={index}
            >
                <div key={key} style={style}>{content}</div>
            </Infinite.CellMeasurer>
        );
    }
}

【问题讨论】:

    标签: react-virtualized


    【解决方案1】:

    recipe you linked to 应该是一个很好的起点。它缺少的主要内容是loadNextPage 的实现,但根据您的状态/数据管理代码的工作方式,不同的应用程序会有所不同。

    我可以从 InfiniteScroller/List 中触发第一次数据加载吗 - 看来您需要传入一个填充有初始页面的数据源

    这取决于你。 IMO 通常只获取记录的第一“页”而不等待InfiniteLoader 询问它们是有意义的——因为你知道你会需要它们。话虽这么说,如果你给InfiniteLoader 一个rowCount 1,然后从isRowLoaded 返回false,它应该请求第一页记录。在 react-virtualized GitHub 中有测试证实了这种行为。

    InfiniteLoader.rowCount 的文档说:“列表中的行数;如果实际数量未知,则可以是任意高数。”

    那么你如何表明没有更多的行了。

    您停止向 rowCount 添加 +1,就像您链接到提及的降价文件一样:

    // If there are more items to be loaded then add an extra row to hold a 
    loading indicator.
      const rowCount = hasNextPage
        ? list.size + 1
        : list.size
    

    【讨论】:

    • 感谢 Brian 的及时回答和反应虚拟化!很快就会有另一个刺,并将在此处更新。
    • 链接到小提琴或我可以运行的东西。我不喜欢通过文本代码 sn-ps 调试问题。效率太低了。 :)
    • 谢谢,我下周可能会这样做。我已经切换到 react-infinite-scroller 作为临时解决方案,因为我现在不想花几天时间在这上面,推迟发布。
    • @brianvaughn 在配方中,MyComponent 函数是什么?它看起来像一个渲染方法,但它有自定义参数。
    • 它是一个 React 组件。这些属性是您将从用于加载外部数据的任何状态管理方法中注入的属性(例如,可能是 Redux,或父组件中的组件 state
    猜你喜欢
    • 1970-01-01
    • 2018-09-18
    • 2017-12-28
    • 2018-11-21
    • 2021-11-27
    • 2017-07-04
    • 2023-04-08
    • 2017-04-20
    • 2020-04-09
    相关资源
    最近更新 更多