美文网首页React native
ReactNative之 FlatList 上拉加载更多

ReactNative之 FlatList 上拉加载更多

作者: 楼上那只猫 | 来源:发表于2019-03-17 15:26 被阅读85次

    FlatList 实现上拉加载更多,关键在于3个属性的设置

    <FlatList
                        style={{flex: 1}}
                        data={records}
                        ListFooterComponent={this.renderFooter}
                        onEndReachedThreshold={0.1}
                        onEndReached={this.loadMore}
                        ListHeaderComponent={
                            <View style={{
                                height: 44,
                                justifyContent: 'center',
                                paddingLeft: 15,
                                backgroundColor: '#f3f4f6',
                            }}>
                                <Text style={{fontSize: 14, color: '#666666'}}>银行转账会扣除转账手续费,以实际到账金额为准</Text>
                            </View>
                        }
                        keyExtractor={(item, index) => index + ''}
                        renderItem={({item, index}) => {
                            return (
                                <JFTRecordItem
                                    key={index + ''}
                                    type={getRecordType(item.type)}
                                    date={moment(item.submitTime).format('YYYY-MM-DD hh:mm:ss')}
                                    cash={item.details.sum + getTradeCurrency(item.details.currency)}
                                    state={getRecordStatus(item.status)}
                                    lineProps={{left: 0}}
                                    onPress={() => this.toRecordDetail(item)}
                                />
    
                            )
                        }}
                    />
    

    onEndReachedThreshold:决定当距离内容最底部还有多远时触发onEndReached回调。注意此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发.
    onEndReached:当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用.
    ListFooterComponent:尾部组件。可以是 React Component, 也可以是一个 render 函数,或者渲染好的 element。这里我们主要是用来渲染加载更多的组件。

    这里我已一个具体的例子来说明。

    1. 首先,这是一个记录列表页面,刚进入页面时,会去请求第一页的数据,同时制定单页的 size
    let page = 1;
    constructor(props) {
            super(props);
            this.state = {
                showFooter: LOAD_MORE_STATE.CANCEL,
                noMoreData:false,
            };
        }
    
        componentDidMount() {
            this.props.getUserCashRecord({pageNum: page, pageSize: 15}).then((response) => {
                if (response.totalCount <= 15) {
                    //总的数据条目少于初始请求的数据,隐藏 footer
                    this.setState({showFooter: LOAD_MORE_STATE.CANCEL});
                }
            }, (err) => {
    
            });
        }
    

    注意到请求完成的回调中,totalCount是服务器返回的记录列表的总数目,如果总数目就已经小于 size 了,那么说明只有一页数据,因此不需要有加载更多的功能。

    1. 如果size 小于 totalCount,说明数据大于1页,需要有加载更多,那么,当滑动到列表底部时,会触发我们在FlatList中设置的回调方法
    loadMore = () => {
            if (this.state.showFooter !== LOAD_MORE_STATE.CANCEL || this.state.noMoreData) {
                return;
            }
            //正在加载中
            this.setState({showFooter: LOAD_MORE_STATE.REFRESHING});
            this.props.getUserCashRecord({pageNum: ++page, pageSize: 15}).then((response) => {
                if (0 === response.commissionList.length) {
                    //全部数据加载完成,显示没有更多数据
                    this.setState({showFooter: LOAD_MORE_STATE.NO_MORE_DATA, noMoreData:true});
                } else {
                    this.setState({showFooter: LOAD_MORE_STATE.CANCEL});
                }
            }, (err) => {
                this.setState({showFooter: LOAD_MORE_STATE.CANCEL});
            });
        };
    

    这个方法可能在一次回调中被多次调用,但是只有在有些情况下,我们才需要让列表进入加载更多的状态。

    这里,如果当前state 的状态不为LOAD_MORE_STATE.CANCEL(也就是说处于REFRESHING或者NO_MORE_DATA状态),或者当前已没有更多数据的话,就直接返回,否则进入加载更多状态

    if (this.state.showFooter !== LOAD_MORE_STATE.CANCEL || this.state.noMoreData) {
                return;
            }
    

    注意,加载更多时 page 要递增,并且,在拿到最新获取的数据后,通过判断最新的数据是否为0来决定最新的刷新状态。

    //正在加载中
            this.setState({showFooter: LOAD_MORE_STATE.REFRESHING});
            this.props.getUserCashRecord({pageNum: ++page, pageSize: 15}).then((response) => {
                if (0 === response.commissionList.length) {
                    //全部数据加载完成,显示没有更多数据
                    this.setState({showFooter: LOAD_MORE_STATE.NO_MORE_DATA, noMoreData:true});
                } else {
                    this.setState({showFooter: LOAD_MORE_STATE.CANCEL});
                }
            }, (err) => {
                this.setState({showFooter: LOAD_MORE_STATE.CANCEL});
            });
    
    1. 最后,是渲染 footer 组件的方法
    renderFooter = () => {
            return <JRNLoadMoreFooter state={this.state.showFooter}/>;
        };
    
    export const LOAD_MORE_STATE = {
        CANCEL:0,   //无需加载更多
        REFRESHING:1, //正在加载更多数据
        NO_MORE_DATA:2, //没有更多数据
    };
    
    class JRNLoadMoreFooter extends PureComponent {
        render() {
            let {state, loadMoreTxt = '正在加载更多数据...', noMoreData = '没有更多数据了'} = this.props;
            return (
                <View>
                    {
                        state === LOAD_MORE_STATE.CANCEL && <View style={{height: 0}}/>
                    }
                    {
                        state === LOAD_MORE_STATE.REFRESHING && <View style={{
                            flexDirection: 'row',
                            height: 34,
                            justifyContent: 'center',
                            backgroundColor:'#fff',
                            alignItems: 'center',
                        }}>
                            <ActivityIndicator/>
                            <Text style={{color: '#999999', fontSize: 13}}>{loadMoreTxt}</Text>
                        </View>
                    }
                    {
                        state === LOAD_MORE_STATE.NO_MORE_DATA &&
                        <View style={{height: 34, alignItems: 'center', justifyContent: 'center', backgroundColor:'#fff'}}>
                            <Text style={{color: '#999999', fontSize: 13}}>{noMoreData}</Text>
                        </View>
                    }
                </View>
    
            )
        }
    }
    
    export default JRNLoadMoreFooter;
    

    注意,在处理加载更多的时候,需要在 reducer 中对最新获得的数据处理,保证是拼接到数据后面

    export const userCashRecordData = handleActions({
        [USER_CASH_RECORD]:(state, {payload}) => {
            if(state.commissionList.length < payload.totalCount) {
                return Object.assign({}, payload, {
                    commissionList: state.commissionList.concat(payload.commissionList)
                });
            } else {
                return state;
            }
        },
    }, {
        commissionList: [],
    });
    

    这里要注意,只有当前 state 中的总数据少于总数据时才拼接,大于的话,直接返回state 即可。

    相关文章

      网友评论

        本文标题:ReactNative之 FlatList 上拉加载更多

        本文链接:https://www.haomeiwen.com/subject/pydumqtx.html