UNPKG

ahooks

Version:
212 lines (211 loc) 8.43 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _tslib = require("tslib"); var _react = require("react"); var _useEventListener = _interopRequireDefault(require("../useEventListener")); var _useMemoizedFn = _interopRequireDefault(require("../useMemoizedFn")); var _useRequest2 = _interopRequireDefault(require("../useRequest")); var _useUpdateEffect = _interopRequireDefault(require("../useUpdateEffect")); var _domTarget = require("../utils/domTarget"); var _rect = require("../utils/rect"); var useInfiniteScroll = function useInfiniteScroll(service) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var target = options.target, isNoMore = options.isNoMore, _options$threshold = options.threshold, threshold = _options$threshold === void 0 ? 100 : _options$threshold, _options$direction = options.direction, direction = _options$direction === void 0 ? 'bottom' : _options$direction, _options$reloadDeps = options.reloadDeps, reloadDeps = _options$reloadDeps === void 0 ? [] : _options$reloadDeps, manual = options.manual, _onBefore = options.onBefore, _onSuccess = options.onSuccess, _onError = options.onError, _onFinally = options.onFinally; var _useState = (0, _react.useState)(), _useState2 = (0, _slicedToArray2["default"])(_useState, 2), finalData = _useState2[0], setFinalData = _useState2[1]; var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2["default"])(_useState3, 2), loadingMore = _useState4[0], setLoadingMore = _useState4[1]; var isScrollToTop = direction === 'top'; // lastScrollTop is used to determine whether the scroll direction is up or down var lastScrollTop = (0, _react.useRef)(undefined); // scrollBottom is used to record the distance from the bottom of the scroll bar var scrollBottom = (0, _react.useRef)(0); // flag: set in onSuccess (bottom direction only) to trigger scrollMethod via effect var pendingBottomScrollCheckRef = (0, _react.useRef)(false); var noMore = (0, _react.useMemo)(function () { if (!isNoMore) { return false; } return isNoMore(finalData); }, [finalData]); var _useRequest = (0, _useRequest2["default"])(function (lastData) { return (0, _tslib.__awaiter)(void 0, void 0, void 0, /*#__PURE__*/_regenerator["default"].mark(function _callee() { var currentData; return _regenerator["default"].wrap(function (_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.next = 1; return service(lastData); case 1: currentData = _context.sent; return _context.abrupt("return", { currentData: currentData, lastData: lastData }); case 2: case "end": return _context.stop(); } }, _callee); })); }, { manual: manual, onFinally: function onFinally(_, d, e) { setLoadingMore(false); _onFinally === null || _onFinally === void 0 ? void 0 : _onFinally(d === null || d === void 0 ? void 0 : d.currentData, e); }, onBefore: function onBefore() { return _onBefore === null || _onBefore === void 0 ? void 0 : _onBefore(); }, onSuccess: function onSuccess(d) { var _a, _b, _c; if (!d.lastData) { setFinalData(Object.assign(Object.assign({}, d.currentData), { list: (0, _toConsumableArray2["default"])((_a = d.currentData.list) !== null && _a !== void 0 ? _a : []) })); } else { setFinalData(Object.assign(Object.assign({}, d.currentData), { list: isScrollToTop ? [].concat((0, _toConsumableArray2["default"])(d.currentData.list), (0, _toConsumableArray2["default"])((_b = d.lastData.list) !== null && _b !== void 0 ? _b : [])) : [].concat((0, _toConsumableArray2["default"])((_c = d.lastData.list) !== null && _c !== void 0 ? _c : []), (0, _toConsumableArray2["default"])(d.currentData.list)) })); } if (isScrollToTop) { setTimeout(function () { // use requestAnimationFrame to ensure the scroll position is updated (To ensure compatibility react 19) requestAnimationFrame(function () { var el = (0, _domTarget.getTargetElement)(target); el = el === document ? document.documentElement : el; if (el) { var scrollHeight = (0, _rect.getScrollHeight)(el); el.scrollTo(0, scrollHeight - scrollBottom.current); } }); }); } else { pendingBottomScrollCheckRef.current = true; } _onSuccess === null || _onSuccess === void 0 ? void 0 : _onSuccess(d.currentData); }, onError: function onError(e) { return _onError === null || _onError === void 0 ? void 0 : _onError(e); } }), loading = _useRequest.loading, error = _useRequest.error, run = _useRequest.run, runAsync = _useRequest.runAsync, cancel = _useRequest.cancel; var loadMore = (0, _useMemoizedFn["default"])(function () { if (noMore) { return; } setLoadingMore(true); run(finalData); }); var runAsyncForCurrent = function runAsyncForCurrent(data) { return (0, _tslib.__awaiter)(void 0, void 0, void 0, /*#__PURE__*/_regenerator["default"].mark(function _callee2() { var res; return _regenerator["default"].wrap(function (_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: _context2.next = 1; return runAsync(data); case 1: res = _context2.sent; return _context2.abrupt("return", res.currentData); case 2: case "end": return _context2.stop(); } }, _callee2); })); }; var loadMoreAsync = (0, _useMemoizedFn["default"])(function () { if (noMore) { return Promise.reject(); } setLoadingMore(true); return runAsyncForCurrent(finalData); }); var reload = function reload() { setLoadingMore(false); return run(); }; var reloadAsync = function reloadAsync() { setLoadingMore(false); return runAsyncForCurrent(); }; var scrollMethod = function scrollMethod() { var el = (0, _domTarget.getTargetElement)(target); if (!el) { return; } var targetEl = el === document ? document.documentElement : el; var scrollTop = (0, _rect.getScrollTop)(targetEl); var scrollHeight = (0, _rect.getScrollHeight)(targetEl); var clientHeight = (0, _rect.getClientHeight)(targetEl); if (isScrollToTop) { if (lastScrollTop.current !== undefined && lastScrollTop.current > scrollTop && scrollTop <= threshold) { loadMore(); } lastScrollTop.current = scrollTop; scrollBottom.current = scrollHeight - scrollTop; } else if (scrollHeight - scrollTop <= clientHeight + threshold) { loadMore(); } }; (0, _useUpdateEffect["default"])(function () { if (!pendingBottomScrollCheckRef.current) { return; } pendingBottomScrollCheckRef.current = false; scrollMethod(); }, [finalData]); (0, _useEventListener["default"])('scroll', function () { if (loading || loadingMore) { return; } scrollMethod(); }, { target: target }); (0, _useUpdateEffect["default"])(function () { run(); }, (0, _toConsumableArray2["default"])(reloadDeps)); return { data: finalData, loading: !loadingMore && loading, error: error, loadingMore: loadingMore, noMore: noMore, loadMore: loadMore, loadMoreAsync: loadMoreAsync, reload: (0, _useMemoizedFn["default"])(reload), reloadAsync: (0, _useMemoizedFn["default"])(reloadAsync), mutate: setFinalData, cancel: cancel }; }; var _default = exports["default"] = useInfiniteScroll;