@orca-fe/hooks
Version:
React Hooks Collections
210 lines (207 loc) • 7.4 kB
JavaScript
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useMemoizedFn } from 'ahooks';
import { useEffect, useRef, useState } from 'react';
var eArr = [];
var loadMoreFlag = {};
export var isFetchResult = value => {
if (value != null && typeof value === 'object') {
if ('data' in value) {
return true;
}
}
return false;
};
export var isPageResult = value => {
if (value != null && typeof value === 'object') {
if ('total' in value && 'list' in value && Array.isArray(value.list) && typeof value.total === 'number') {
return true;
}
}
return false;
};
export function defaultFormatter(res) {
var t = res;
if (isFetchResult(t)) {
t = t.data;
}
if (isPageResult(t)) {
return t;
}
throw new Error('[useLoadMore] Service result is not a page result. Please use formatter to convert the result to `PageResultType`.');
}
export function useLoadMore(_service, options = {}) {
var _stateMgr$state, _stateMgr$setState, _data$list2;
var _options$defaultParam = options.defaultParams,
defaultParams = _options$defaultParam === void 0 ? [] : _options$defaultParam,
_options$manual = options.manual,
manual = _options$manual === void 0 ? false : _options$manual,
_options$pageSize = options.pageSize,
pageSize = _options$pageSize === void 0 ? 10 : _options$pageSize,
onError = options.onError,
onSuccess = options.onSuccess,
_options$formatter = options.formatter,
formatter = _options$formatter === void 0 ? defaultFormatter : _options$formatter,
stateMgr = options.stateMgr,
onFinish = options.onFinish;
var service = useMemoizedFn(_service);
// 组件状态控制 start
var _useState = useState(() => ({
loading: false,
data: {
list: [],
total: 0
},
page: 1,
params: defaultParams
})),
_useState2 = _slicedToArray(_useState, 2),
__state = _useState2[0],
__setState = _useState2[1];
var state = (_stateMgr$state = stateMgr === null || stateMgr === void 0 ? void 0 : stateMgr.state) !== null && _stateMgr$state !== void 0 ? _stateMgr$state : __state;
var _setState = (_stateMgr$setState = stateMgr === null || stateMgr === void 0 ? void 0 : stateMgr.setState) !== null && _stateMgr$setState !== void 0 ? _stateMgr$setState : __setState;
var _this = useRef({
unloaded: false,
ticket: 0,
loading: false
}).current;
var setState = useMemoizedFn((newState = {}) => {
if (!_this.unloaded) {
_setState(state => _objectSpread(_objectSpread({}, state), newState));
}
});
// 组件状态控制 end
var _state$loading = state.loading,
loading = _state$loading === void 0 ? false : _state$loading,
data = state.data,
error = state.error,
params = state.params,
_state$page = state.page,
page = _state$page === void 0 ? 1 : _state$page;
// 发起请求
var load = useMemoizedFn( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(..._args) {
var isLoadMore, args, pageIndex, ticket, _res, formattedData, _data$list;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
// 取第一个参数判断是否加载更多
isLoadMore = _args[0] === loadMoreFlag; // 取得参数(如果是加载更多,需要从 state 中取得参数)
args = isLoadMore ? params !== null && params !== void 0 ? params : defaultParams : _args;
pageIndex = isLoadMore ? page + 1 : 1;
ticket = performance.now();
_this.ticket = ticket;
_this.loading = true;
setState({
loading: true,
error: undefined
});
_context.prev = 7;
_context.next = 10;
return service({
pageIndex,
pageSize
}, ...args);
case 10:
_res = _context.sent;
formattedData = formatter(_res);
if (!(formattedData == null)) {
_context.next = 14;
break;
}
throw new Error('[useLoadMore] Formatted result is undefined');
case 14:
if (_this.ticket === ticket) {
// 请求结果有效
_this.loading = false;
setState({
params: args,
loading: false,
data: isLoadMore ? {
list: [...((_data$list = data === null || data === void 0 ? void 0 : data.list) !== null && _data$list !== void 0 ? _data$list : []), ...formattedData.list],
total: formattedData.total
} : formattedData,
page: pageIndex
});
if (formattedData != null) {
if (typeof onSuccess === 'function') {
onSuccess(formattedData, args);
}
} else if (typeof onError === 'function') {
onError(new Error('result is undefined'), args);
}
if (typeof onFinish === 'function') {
onFinish(_res, args);
}
} else {
console.warn('Request response out date.');
}
return _context.abrupt("return", formattedData);
case 18:
_context.prev = 18;
_context.t0 = _context["catch"](7);
console.error(_context.t0);
_this.loading = false;
setState({
data: {
list: [],
total: 0
},
error: _context.t0,
loading: false
});
if (typeof onError === 'function') {
onError(_context.t0, args);
}
case 24:
return _context.abrupt("return", undefined);
case 25:
case "end":
return _context.stop();
}
}, _callee, null, [[7, 18]]);
})));
var run = useMemoizedFn(load);
var loadMore = useMemoizedFn( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
return _context2.abrupt("return", load(loadMoreFlag));
case 1:
case "end":
return _context2.stop();
}
}, _callee2);
})));
var cancel = useMemoizedFn(() => {
_this.ticket = Date.now();
});
useEffect(() => {
_this.loading = false;
_this.unloaded = false;
// 如果 manual === false,则需要主动加载一次
if (!manual) {
load(...defaultParams);
}
return () => {
_this.unloaded = true;
};
}, []);
var list = (_data$list2 = data === null || data === void 0 ? void 0 : data.list) !== null && _data$list2 !== void 0 ? _data$list2 : eArr;
var total = (data === null || data === void 0 ? void 0 : data.total) || 0;
return {
loading,
params,
data: list,
total,
page,
hasMore: list.length < total,
error,
run,
loadMore,
cancel
};
}
export default useLoadMore;