【问题标题】:React Native List View - Prepend items without rendering whole listReact Native List View - 在不渲染整个列表的情况下添加项目
【发布时间】:2015-11-20 09:58:40
【问题描述】:

我正在尝试使用拉动刷新功能实现无限滚动。 我得到了新数据,通过concat 附加它,它渲染得很好。问题是它用它渲染了整个列表。如果我有超过 500 件物品,那将是一场噩梦。

onRefresh() {
    var posts = this.state.posts;
    var firstPost = posts[0].m._id;

    server.getStream('', firstPost, 4000)
        .then(res => {
             posts = res.concat(posts);
             this.setState({
                dataSource: this.ds.cloneWithRows(posts),
                posts
             });
             this.swipeRefreshLayout && this.swipeRefreshLayout.finishRefresh();
        })

}

有没有办法告诉 RN 只呈现新行?可能是某种key 道具?

谢谢

更新

DatSource 中的 rowHasChanged 比较器不会触发。我认为我构建组件的方式可能与它有关。

renderRow(post) {

    if(post === 'loader') {
        return (
            <ProgressBarAndroid 
                styleAttr="Large" 
                style={styles.spinnerBottom}/>
        )
    }

    let hasLoader = post.m._id === lastPostId;

    let loader = hasLoader ? 
        <ProgressBarAndroid 
            styleAttr="Large" 
            style={styles.spinnerBottom}/> : null;

    return (
        <View>
            <Post 
                post={post}
                isLoadingTop={isLoadingTop}/>
            {loader}
        </View> 
    )
}

render() {

    var stream = <ListView
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow.bind(this)}
                    onEndReached={this.onEndReached.bind(this)}
                    onEndReachedThreshold={1}
                    pageSize={15} />


    return (
        <View style={styles.mainContainer}>
            <View style={styles.header}>
                <Text style={styles.headerText}>Header</Text>
            </View>
            <SwipeRefreshLayoutAndroid
                ref={(c) => { 
                    this.swipeRefreshLayout = c;
                }}
                onRefresh={this.onRefresh.bind(this)}>
                {stream}
            </SwipeRefreshLayoutAndroid>
        </View>
    );

有什么想法吗?

【问题讨论】:

    标签: react-native


    【解决方案1】:

    您需要实现DataSource.rowHasChanged 比较器,使其为数据未更改的行呈现false。在现有列表项没有改变的情况下,您可以使用简单的引用相等检查:

    let dataSource = new ListView.DataSource({
      rowHasChanged: (prev, next) => prev !== next
    });
    

    如果您不想更改的行与之前渲染过程中使用的对象不同,则需要实现更具体的比较器函数。

    【讨论】:

    • 我有..我认为:this.ds = new ListView.DataSource({ rowHasChanged: (row1, row2) =&gt; { return row1 !== row2 } }); 我在函数内部尝试了console.log,但它没有记录任何内容。由于某种原因它没有执行。
    • @RadoMilushev 据我所知,它应该可以工作。在我的应用中工作,刚刚测试过。
    • 你能用你的实现来更新你的答案吗?我怀疑我的结果是一些微不足道的错误,但这让我发疯。谢谢。
    • 上面已经是我代码库中的实现了。但是,您似乎是在 Android 上开发,而我的应用程序仅适用于 iOS。也许那里有什么问题?
    猜你喜欢
    • 2016-12-29
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多