首页 > 其他分享 >React Native -- FlatList 之 下拉刷新,上拉加载

React Native -- FlatList 之 下拉刷新,上拉加载

时间:2022-11-09 15:03:25浏览次数:48  
标签:loading return FlatList .. -- currentPageNo React import const

FlatList组件

import React, { FC, useEffect, useState, useRef } from 'react';
import { ActivityIndicator, FlatList as RNFlastList, FlatListProps } from 'react-native';
import { Text, View, ViewProps } from 'react-native-ui-lib';
import { ViewLoader, WidthSpace } from '..';

type IFlatListWithRematchProps<T = any> = FlatListProps<T> & {
  flex?: boolean;
  pageSize?: number; // 每页展示个数
  onEndCB?: () => void; // 每次分页执行的回调
  fetchDataFn: any;
  currentPageNo: number;
  totalCount: number;
  pageToNextFn: any;
  loading: boolean;
  isNeedBigLoading: boolean;
  triggerPageNo: number;
  triggerListType?: string;
};

// 分页组件
const FlatList: FC<IFlatListWithRematchProps> = ({
  flex = true,
  pageSize = 10,
  fetchDataFn, // 接口调用函数,封装为promise,执行.then处理接口返回的数据
  pageToNextFn, // 上滑加载执行的函数
  triggerPageNo, // 用于触发接口调用函数的执行,一旦监听到外部pageNo更新,接口调用函数重新执行
  triggerListType, // 用于页面存在多个tab,在切换tab时,需要分页组件同样监听到外部pageNo更新,接口调用函数重新执行, 如果页面不存在tab则用不到这个参数
  loading,
  isNeedBigLoading = false, //是否在 ViewLoader上面加 loading
  onEndCB, // 上滑加载完成后的额外执行函数
  ...restProps
}) => {
  const [currentPageNo, setCurrentPageNo] = useState(1);
  const [totalCount, setTotalCount] = useState(0);
  const [results, setResults] = useState([]);
  const totalPage = Math.ceil(totalCount / pageSize);
  const flatListRef = useRef<any>();
  useEffect(() => {
    if (triggerPageNo > 0 && totalPage > 0 && triggerPageNo >= totalPage) return;
    fetchDataFn.then((res: { pageNo: number; totalCount: number; results: [] }) => {
      setCurrentPageNo(res.pageNo);
      setTotalCount(res.totalCount);
      setResults(res.results);
    });
    // 重新从头开始请求时,页面滚动到顶部
    if (triggerPageNo === 0) {
      flatListRef?.current?.scrollToOffset({ animated: false, offset: 0 });
    }
    return () => {
      console.log('clear');
    };
  }, [triggerPageNo, triggerListType]);


  useEffect(() => {
    // 切换tab时,要求列表上滑到顶部
    if (triggerListType) {
      flatListRef?.current?.scrollToOffset({ animated: true, offset: 0 });
    }
  }, [triggerListType]);

  const onEndReached = () => {
    if (currentPageNo < totalPage) {
      onNext();
      onEndCB && onEndCB();
    }
  };

  const onNext = () => {
    pageToNextFn();
  };

  const emptyComponent = () => {
    if (!loading && totalCount === 0) {
      return (
        <View center padding-30 paddingT-120>
          <Text artTitle grey99>
            暂无更多数据...
          </Text>
        </View>
      );
    }
    return <View />;
  };
  const footerComponent = () => {
    //console.log('footerComponent', currentPageNo, totalPage);
    if (currentPageNo < totalPage || loading)
      //
      return (
        <View row center padding-15>
          <ActivityIndicator size="small" />
          <WidthSpace />
          <Text artTitle grey99>
            正在加载中...
          </Text>
        </View>
      );
    if (currentPageNo === totalPage && currentPageNo !== 0 && totalPage > 0) {
      return (
        <View padding-15 center>
          <Text artTitle grey99>
            没有更多了...
          </Text>
        </View>
      );
    }
    return <View></View>;
  };

  // loading={loading} 不使用View层的loading,分页统一使用分页自己的小loading
  return (
    <ViewLoader flex={flex} loading={isNeedBigLoading ? loading : false}>
      <RNFlastList
        ref={flatListRef}
        data={results}
        onEndReached={onEndReached}
        onEndReachedThreshold={0.2}
        ListFooterComponent={footerComponent}
        ListEmptyComponent={emptyComponent}
        {...restProps}
      />
    </ViewLoader>
  );
};

export const NoData: FC<ViewProps & { title?: string }> = ({
  title = '暂无更多数据...',
  ...restProps
}) => (
  <View center padding-30 {...restProps}>
    <Text artTitle grey99>
      {title}
    </Text>
  </View>
);

export const onl oad: FC<ViewProps & { title?: string; loading?: boolean }> = ({
  loading = false,
  title = '正在加载中...',
}) => {
  if (loading)
    return (
      <View row center padding-15>
        <ActivityIndicator size="small" />
        <WidthSpace />
        <Text artTitle grey99>
          {title}
        </Text>
      </View>
    );
  return <></>;
};

export default FlatList;

FlatListDemo

// 社区Tab下 动态Tab页 import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; // @ts-ignore import { RefreshNormalHeader } from 'react-native-smart-refresh'; import { View, Colors } from 'react-native-ui-lib'; import { DispatchPro, RootState } from '../../../store'; import { WidthSpace, LineSpace, FlatList } from '../../../components'; import { IDaynamicItem } from '../../../models/community/ICommunity.module'; import DaynamicItem from '../components/daynamicItem';
type ICommunity = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>; const Daynamic = (props: ICommunity) => {   const { fetchDaynamicCarousel, fetchAnnouncementList, fetchDaynamicList, daynamicLoading, shareStatus } = props;
  const [daynamicList, setDaynamicList] = useState<IDaynamicItem[]>([]); // 动态列表数据   const [currentPageNo, setCurrentPageNo] = useState(-1); // 动态列表分页   // 页面初始化时,请求数据   const initRequest = () => {     fetchDaynamicCarousel({       params: {         pageTypeId: '1', // 页面类型;1-动态头部广告;2-文化每日分享运营位       },       apiName: 'fetchDaynamicCarousel',     });     fetchAnnouncementList({       params: {},       apiName: 'fetchAnnouncementList',     });   };
  useEffect(() => {     initRequest();     setCurrentPageNo(0);   }, []);   useEffect(() => {     if (shareStatus === 'success') {       onRefresh();     }   }, [shareStatus]);   const onRefresh = () => {     setDaynamicList([]);     setCurrentPageNo(-1);     setTimeout(() => {       initRequest();       setCurrentPageNo(0);     }, 500);   };
  // 请求动态列表数据,距离底部还有0.2 时触发 注意此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。   const fetchDataFn = React.useMemo(() => new Promise((resolve) => {     if (currentPageNo < 0) return;     fetchDaynamicList       && fetchDaynamicList({         params: { pageNo: currentPageNo + 1, pageSize: 10, pageTypeId: '1', associationId: '' },         apiName: 'fetchDaynamicList',       }).then(res => {         setDaynamicList([...daynamicList, ...(res?.shareInfoList || [])]);         resolve({           pageNo: currentPageNo + 1,           totalCount: res?.totalCount,           results: [...daynamicList, ...(res?.shareInfoList || [])],         });       });   }), [currentPageNo]);
  const pageToNextFn = () => {     setCurrentPageNo(currentPageNo + 1);   };   return (     <FlatList       loading={daynamicLoading}       isNeedBigLoading       refreshControl={         <RefreshNormalHeader           refreshing={daynamicLoading}           onRefresh={onRefresh}           containerStyle={{             paddingLeft: 10,             paddingBottom: 30,             alignItems: 'flex-end',           }}           titleStyle={{ fontSize: 14 }}           timeStyle={{ display: 'none', fontSize: 14 }}           leftContainerStyle={{ marginBottom: -6, marginRight: -35 }}           activityIndicatorProps={{ color: Colors.primaryColor }}         />       }       fetchDataFn={fetchDataFn}       pageToNextFn={pageToNextFn}       triggerPageNo={currentPageNo}       keyExtractor={(item: IDaynamicItem, index: number) => `${item.shareId}_${item.typeId}_${index}`}       renderItem={({ item }: { item: IDaynamicItem }) => {         return <View>           <LineSpace height={15} />           <View row>             <WidthSpace width={15} />             <DaynamicItem data={item} />           </View>         </View>;       }}     />   ); };
const mapStateToProps = ({   community: { daynamicCarouselData, announcementSingleData, daynamicList, daynamicLoading, shareStatus }, }: RootState) => ({ daynamicCarouselData, announcementSingleData, daynamicList, daynamicLoading, shareStatus }); const mapDispatchToProps = ({   community: { fetchDaynamicCarousel, fetchAnnouncementList, fetchDaynamicList }, }: DispatchPro) => ({   fetchDaynamicCarousel,   fetchAnnouncementList,   fetchDaynamicList, });
export default connect(mapStateToProps, mapDispatchToProps)(Daynamic);

 

标签:loading,return,FlatList,..,--,currentPageNo,React,import,const
From: https://www.cnblogs.com/zpy521hl/p/16873673.html

相关文章

  • 【操作系统】CPU的工作模式
    目录一、实模式二、保护模式三、长模式四、总结本文为《操作系统45讲》笔记,简要介绍X86CPU的工作模式,实模式,保护模式,长模式。参考:操作系统实战45讲一、实模式(1)真实真......
  • 【BUG记录】com.alibaba.nacos.api.exception.NacosException: Request nacos server
    BUG背景使用docker搭建nacos服务后,准备用java客户端连接nacosserver的时候出现了如下问题,连接不上。(可能和大家的导致的问题不一样)BUG日志如下的报错可以看见gprc的字眼,咦,......
  • 问题解决-白鹭引擎Egret Wing3修改项目内容后进行调试,项目仍显示修改前样式
    问题描述:修改前: 修改后: 解决方法:点击上方菜单栏项目-清理,进行项目清理    点击菜单栏项目-调试  重新进行调试。  调试成功后,问题成功解......
  • Vue学习记录--实现列表的添加删除以及查找功能
    1.x版本中的filterBy指令,在2.x中已经被废除:​​filterBy-指令​​<trv-for="iteminlist|filterBysearchNamein'name'"><td>{{item.id}}</td><td>{{item.name......
  • 树链剖分入门
    树链剖分入门本人初学,若有错误恳请大佬在评论区指出,谢谢!一,它能干嘛恶心你解决树上路径/子树等问题。情景引入老师:给一棵点权树和一些操作,每次操作选两个点,把这两个点......
  • Vue学习记录--定义局部子组件以及组件切换
    使用​​components​​属性定义局部子组件组件实例定义方式:<script>//创建Vue实例,得到ViewModelvarvm=newVue({el:'#app',data:{},me......
  • 高数-微分
    前言以下截图来自bilibili的宋浩老师陈杰老师,我不生产资源,我只是资源的搬运工。宋浩老师的课适合一刷,陈杰老师的适合二刷,最后就是自己刷题复习了,如果大一大二没有认真听......
  • kafka Java客户端之 consumer API 消费消息
    背景:我使用docker-compose搭建的kafka服务​kafka的简单介绍以及docker-compose部署单主机Kafka集群​​使用consumerAPI消费指定Topic里面的消息首先我们需要使用AdminA......
  • 技术分享:IPv6升级转换常见问题盘点
                 随着IPv6网络的普及,IPv6环境的问题处理已经成为网站管理员的必修课,但是由于绝大部分网站运维人员对IPv6网络的接触都不深,因此网站进行IPv6......
  • 小程序promise封装
    小程序promise封装//ajaxpromise封装constrequestFetch=(url,method,param)=>{//一个页面中可能会发送多个请求,ajaxTimes记载同时发送异步请求代码的次数,目......