UNPKG

rc-hooks

Version:
125 lines (124 loc) 7.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = require("react"); var ut2_1 = require("ut2"); var useAsync_1 = tslib_1.__importDefault(require("../useAsync")); var useScrollToLower_1 = tslib_1.__importDefault(require("./useScrollToLower")); var useUpdateEffect_1 = tslib_1.__importDefault(require("../useUpdateEffect")); /** * 基于 `useAsync` 扩展,用于管理加载更多的 Hook。 * * @param {number} [options.threshold=100] 上拉自动加载,距离底部距离阈值。默认 `100`。 * @param {Object | Function} [options.target] 内容的滚动容器,如果存在,则在滚动到底部时,自动触发 `loadMore` 方法。 * @param {Function} [options.isNoMore=()=>false] 判断是否没有更多数据。默认 `()=>false`。 * @param {boolean} [options.autoRun=true] 在初始化时自动执行异步函数。如果设置为 `false`,则需要手动调用 `run` 触发执行。默认 `true`。 * @param {*} [options.initialData] 初始化的 `data`。 * @param {boolean} [options.defaultLoading] 初始化默认 `loading` 值。默认值等于 `autoRun && !loadingDelay`。 * @param {Array} [options.defaultParams] 如果 `autoRun=true` 自动执行 `run` 的默认参数。 * @param {Array} [options.refreshDeps] 在 `autoRun = true` 时,refreshDeps 变化,会执行 `refresh` (重置`current`到第 1 页,并清除之前列表数据,发起请求。)。 * @param {Function} [options.onBefore] 异步函数执行前触发,参数为 `params`。 * @param {Function} [options.onSuccess] 异步函数 `resolve` 时触发,参数为 `data` 和 `params`。 * @param {Function} [options.onError] 异步函数报错时触发,参数为 `error` 和 `params`。 * @param {number} [options.loadingDelay] 设置 `loading` 延迟时间,避免闪烁,单位为毫秒。 * @param {boolean} [options.refreshOnWindowFocus=false] 在屏幕重新获取焦点或重新显示时,是否重新发起请求。如果为 `false`,不会重新发起请求。如果为 `true`,在屏幕重新聚焦或重新显示时,会重新发起请求。默认 `false`。 * @param {number} [options.focusTimespan=5000] 屏幕重新聚焦,重新发起请求时间间隔。需要配置 `refreshOnWindowFocus` 使用。默认 `5000`。 * @param {number} [options.debounceInterval] 防抖间隔,单位为毫秒,设置后,请求进入防抖模式。 * @param {number} [options.throttleInterval] 节流间隔,单位为毫秒,设置后,请求进入节流模式。 * @returns {Object} * @example * const { data, error, loading, loadingMore, noMore, loadMore, refresh, cancel } = useLoadMore(asyncFn, options); */ function useLoadMore(asyncFn, options) { var _this = this; var _a = (options || {}), _b = _a.threshold, threshold = _b === void 0 ? 100 : _b, target = _a.target, _c = _a.isNoMore, isNoMore = _c === void 0 ? function () { return false; } : _c, _d = _a.refreshDeps, refreshDeps = _d === void 0 ? [] : _d, _e = _a.autoRun, autoRun = _e === void 0 ? true : _e, restOptions = tslib_1.__rest(_a, ["threshold", "target", "isNoMore", "refreshDeps", "autoRun"]); var dataGroup = (0, react_1.useRef)([]); // 缓存之前请求的列表数据 var currentPageRef = (0, react_1.useRef)(1); // 当前页码 var _f = (0, useAsync_1.default)(asyncFn, tslib_1.__assign(tslib_1.__assign({ defaultParams: [ { current: currentPageRef.current } ], autoRun: autoRun }, restOptions), { onError: function (err, _params) { var _a; // 加载失败并且当前页码大于第一页,页码自减一 if (currentPageRef.current > 1) { currentPageRef.current -= 1; } (_a = restOptions === null || restOptions === void 0 ? void 0 : restOptions.onError) === null || _a === void 0 ? void 0 : _a.call(restOptions, err, _params); }, __INTERNAL_FORMAT__: function (res) { dataGroup.current = currentPageRef.current === 1 ? res.list : dataGroup.current.concat(res.list); return tslib_1.__assign(tslib_1.__assign({}, res), { list: dataGroup.current }); } })), run = _f.run, data = _f.data, loading = _f.loading, reqCancel = _f.cancel, params = _f.params, reqMutate = _f.mutate, restAsyncReturn = tslib_1.__rest(_f, ["run", "data", "loading", "cancel", "params", "mutate"]); var noMore = isNoMore ? !loading && isNoMore(data) : false; var _g = tslib_1.__read(params || []), firstParams = _g[0], restParams = _g.slice(1); var loadData = (0, react_1.useCallback)(function () { return run.apply(void 0, [{ current: currentPageRef.current }].concat(restParams)); }, [restParams, run]); var cancel = (0, react_1.useCallback)(function () { // 加载中并且当前页码大于第一页,页码自减一 if (loading && currentPageRef.current > 1) { currentPageRef.current -= 1; } reqCancel(); }, [reqCancel, loading]); /** * 触发加载更多。 */ var loadMore = (0, react_1.useCallback)(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { if (loading || noMore) { return [2 /*return*/]; } currentPageRef.current += 1; return [2 /*return*/, loadData()]; }); }); }, [loading, noMore, loadData]); var mutate = (0, react_1.useCallback)(function (param) { var res = typeof param === 'function' ? param(data) : param; dataGroup.current = (res === null || res === void 0 ? void 0 : res.list) || []; reqMutate(res); }, [data, reqMutate]); var refresh = (0, react_1.useCallback)(function () { cancel(); currentPageRef.current = 1; mutate(function (d) { return (tslib_1.__assign(tslib_1.__assign({}, d), { list: [] })); }); return loadData(); }, [cancel, loadData, mutate]); var scrollMethod = (0, react_1.useCallback)(function () { if (loading || !target) { return; } return loadMore(); }, [loadMore, target, loading]); (0, useScrollToLower_1.default)({ target: target, threshold: threshold, onScrollLower: scrollMethod }); (0, useUpdateEffect_1.default)(function () { if (autoRun && (0, ut2_1.isArray)(refreshDeps) && refreshDeps.length > 0) { refresh(); } }, refreshDeps); return tslib_1.__assign(tslib_1.__assign({}, restAsyncReturn), { loading: loading, data: data, run: run, /** * 重置`current`到第 `1` 页,并清除之前列表数据,发起请求。 */ refresh: refresh, cancel: cancel, mutate: mutate, params: [tslib_1.__assign(tslib_1.__assign({}, firstParams), { current: currentPageRef.current })].concat(restParams), /** * 触发加载更多。 * * 如果没有更多或者正在加载中,返回 `undefined`。 */ loadMore: loadMore, /** * 是否正在加载更多。即加载中并且 `current` 不等于 `1`。 */ loadingMore: loading && currentPageRef.current > 1, /** * 是否没有更多。 */ noMore: noMore }); } exports.default = useLoadMore;