RN - ScrollView嵌套FlatList场景实现上拉加载分页

方法一简单介绍下未嵌套ScrollViewFlatList上拉加载应用场景,可自行忽略,直接跳至方法二嵌套scrollView场景。

一、FlatList未嵌套在ScrollView的应用场景

1、最简单的方法是应用react-native-refresh-list-view组件实现,其基于FlatList的二次封装。

通过控制RefreshState来实现下拉刷新或者上拉加载。

export const RefreshState = {
  Idle: 0,
  HeaderRefreshing: 1,
  FooterRefreshing: 2,
  NoMoreData: 3,
  Failure: 4,
  EmptyData: 5,
}

具体应用的部分代码如下:

import RefreshListView, { RefreshState } from "react-native-refresh-list-view";

renderRefreshList = () => {
    const { sourceData, refreshState } = this.state;
    return (
      <RefreshListView
        data={sourceData}
        ItemSeparatorComponent={() => this.renderSeparator()}
        keyExtractor={(item, idx) => idx.toString()}
        renderItem={({ item }) => this.renderCell(item)}
        ListHeaderComponent={this.renderHeader}
        refreshState={refreshState}
        onHeaderRefresh={this.onHeaderRefresh}
        onFooterRefresh={() => this.onCheckMore()}
        footerNoMoreDataText="已经到底了"
      />
    );
  };

2、如果不想使用方法1中的第三方组件,可以自定义上拉加载的组件

核心属性: onEndReachedThresholdonEndReached

onEndReachedThreshold设置大于1时,的确进入页面就触发,设置在0-1之间时按正常逻辑走。

<FlatList 
      ...  
     onEndReachedThreshold={0.5}
      ...
/>

上拉加载更多onReached被触发两次,造成重复请求资源,性能浪费

<FlatList
    ...
    onEndReached={() => {
    if (this.canLoadMore) {
        this.loadData(true); //
        this.canLoadMore = false;
    }
    }}
    onEndReachedThreshold={0.5}
    onMomentumScrollBegin={() => {
    this.canLoadMore = true; //初始化时调用onEndReached的loadMore
    }}
    ...
/>

通常情况下是先调用onMomentumScrollBegin,然后调用onEndReached,但是可能会存在意外情况

<FlatList
    ...
    onEndReached={() => {
    setTimeout(() => {
        if (this.canLoadMore) {
            this.loadData(true);
            this.canLoadMore = false;
        }
    }, 100)
    }}
    onEndReachedThreshold={0.5}
    onMomentumScrollBegin={() => {
    this.canLoadMore = true; //初始化时调用onEndReached的loadMore
    }}
    ...
/>

二、FlatList嵌套在ScrollView的应用场景

FlatList(或ListView)和其他子组件在外面加了一个ScrollView时,debugg发现在一直不停地触发onEndReached函数,也就是说父组件ScrollView能滚动,导致FlatList(或ListView)中的数据不能满屏,于是就不停地触发该函数,不停fetch请求。

还有,当FlatList(或ListView)的dataSource第一次渲染时,如果为空,也会触发onEndReached函数。

解决方案: 针对此问题,直接对最外层的scrollview实现上拉加载功能

  renderScrollView = () => {
    const { isRefreshing } = this.state;
    return (
      <ScrollView
        onScroll={event => this.onScroll(event)}
        scrollEventThrottle={1}
        onMomentumScrollEnd={this.handleScrollEnd}
        refreshControl={
          <RefreshControl
            tintColor="#FFFFFF"
            refreshing={isRefreshing}
            onRefresh={() => this.onRefresh()}
          />
        }
      >
        {this.renderView()}
      </ScrollView>
    );
  };


 // 判断上拉加载的时机
  handleScrollEnd = event => {
    const contentHeight = event.nativeEvent.contentSize.height;
    const scrollViewHeight = event.nativeEvent.layoutMeasurement.height;
    const scrollOffset = event.nativeEvent.contentOffset.y;

    // 是否滑动到底部
    const isEndReached = scrollOffset + scrollViewHeight >= contentHeight;
    // 内容高度是否大于列表高度
    const isContentFillPage = contentHeight >= scrollViewHeight;

    const { reqSsqData, reqJpqData, reqWbqData, reqInData } = this.state;

    if (isContentFillPage && isEndReached) {
      // 已滑动scrollview底部,触发加载分页请求
    }
  };
需要注意:

在判断上拉加载的时机时,主要是比较以下2个时机,根据自己的需求添加

// 滚动结束的回调
onMomentumScrollEnd={this.handleScrollEnd}

// 手指松开屏幕的回调
 onScrollEndDrag={this.handleScrollEnd}

参考:
https://www.jianshu.com/p/33ec6ceeb638
https://www.cnblogs.com/fe-linjin/p/10587720.html
https://blog.csdn.net/qq_21478985/article/details/80931386

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容