封装了一个react下拉刷新上拉加载组件
2019-07-31 本文已影响0人
JsLin_
useState,useEffect,React.memo,Ts 使用等
import React, { useState, useEffect} from 'react'
import { ListView, Icon } from 'antd-mobile';
import PullToRefresh from 'rmc-pull-to-refresh'; //antd rmc-pull-to-refresh
import style from './index.module.scss'
import Result from '@components/result/result';
/**
* @description: 下拉刷新传参
* @param {IProps}: IProps
*/
interface IProps {
requestFun: Function;
requestParams?: Object;
renderRow: Function;
renderHead?: Function;
scroHeight?: number;
}
let initData: any[];
const pageSize: number = 10; //初始化默认页
let pageNum: number = 1; //第几页
export default React.memo(({ requestFun, requestParams, renderRow, renderHead, scroHeight }: IProps) => {
const dataSourceInit = new ListView.DataSource({
rowHasChanged: (row1: any, row2: any) => row1 !== row2,
});
const [dataSource, setDataSource] = useState(dataSourceInit);
const [refreshing, setRefreshing] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [hasMore, setHasMore] = useState(true);
const [heightInit] = typeof scroHeight === 'number' ? useState(scroHeight) : useState(document.documentElement.clientHeight);
const [useBodyScroll] = useState(false);
const [isNoResult, setIsNoResult] = useState(false);
useEffect(() => {
fetchData()
if (useBodyScroll) {
document.body.style.overflow = 'auto';
} else {
document.body.style.overflow = 'hidden';
}
}, [requestParams])
const fetchData = async (num?: number) => {
const pageNumVal = typeof num === 'number' ? pageNum : 1;
const paramsVal = Object.assign(
{
pageSize,
// tslint:disable-next-line:trailing-comma
pageNum: pageNumVal
},
// tslint:disable-next-line:trailing-comma
requestParams
)
const resultResponser = await requestFun(paramsVal);
const { code, list, hasNext } = resultResponser;
if (code === 200) {
pageNum = pageNumVal;
initData = pageNum === 1 ? list : initData.concat(list);
if (pageNum === 1 && (!!!list || list.length === 0)) {
setIsNoResult(true)
}
}
setRefreshing(false)
if (hasNext === 0) {
setHasMore(false)
setIsLoading(false)
}
setDataSource(dataSource.cloneWithRows(initData));
}
const onRefresh = () => {
setRefreshing(true)
setIsLoading(true)
fetchData()
};
const onEndReached = (event: any) => {
if (!isLoading && !hasMore) {
return false;
}
setIsLoading(true)
fetchData(++pageNum)
setIsLoading(false)
};
const separator = (sectionID: any, rowID: any) => (
<div
key={`${sectionID}-${rowID}`}
style={{
backgroundColor: '#F5F5F9',
height: 15,
}}
/>
);
const row = (rowData: any, sectionID: any, rowID: any) => renderRow(rowData, sectionID, rowID);
const renderHeader = () => {
if (typeof renderHead === 'function') {
return renderHead()
} else {
return null
}
}
return (
<>
{
!isNoResult ?
<ListView
className={style.ownHeader}
key={useBodyScroll ? '0' : '1'}
dataSource={dataSource}
renderHeader={renderHeader}
renderFooter={() => (<div style={{ padding: 30, textAlign: 'center', border: 'none' }}>
{isLoading ? '加载中..' : '数据已加载全部'}
</div>)}
renderRow={row}
renderSeparator={separator}
useBodyScroll={useBodyScroll}
style={useBodyScroll ? {} : {
height: heightInit,
// border: '1px solid #ddd',
margin: '30px 0',
}}
pullToRefresh={
<PullToRefresh
indicator={{
deactivate: <div></div>,
activate: <div className={style.freshFont}>松开立即刷新</div>,
release: <div className={style.activeStyle}>
<Icon type="loading" color="#fed224" />
</div>,
finish: <div className={style.freshFont}></div>
}}
refreshing={refreshing}
onRefresh={onRefresh}
></PullToRefresh>}
onEndReached={onEndReached}
onEndReachedThreshold={10}
/>
:
<Result />
}
</>
);
});