UNPKG

@orca-fe/hooks

Version:

React Hooks Collections

227 lines (223 loc) 8.18 kB
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime"; import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; /* eslint-disable @typescript-eslint/no-explicit-any */ import { useDocumentVisibility, useMemoizedFn } from 'ahooks'; import React, { useContext, useEffect, useRef, useState } from 'react'; import useInterval from "./useInterval"; export var isFetchResult = value => { if (value != null && typeof value === 'object') { if ('data' in value) { return true; } } return false; }; export var UseServiceContext = /*#__PURE__*/React.createContext({}); var cache = {}; export function defaultFormatter(res) { if (isFetchResult(res)) { return res.data; } return res; } export function useService(_service, options = {}) { var _stateMgr$state, _stateMgr$setState; var globalOptions = useContext(UseServiceContext); var _globalOptions$option = _objectSpread(_objectSpread({}, globalOptions), options), _globalOptions$option2 = _globalOptions$option.defaultParams, defaultParams = _globalOptions$option2 === void 0 ? [] : _globalOptions$option2, initialData = _globalOptions$option.initialData, _globalOptions$option3 = _globalOptions$option.manual, manual = _globalOptions$option3 === void 0 ? false : _globalOptions$option3, onError = _globalOptions$option.onError, onSuccess = _globalOptions$option.onSuccess, cacheKey = _globalOptions$option.cacheKey, _globalOptions$option4 = _globalOptions$option.keepSuccessData, keepSuccessData = _globalOptions$option4 === void 0 ? true : _globalOptions$option4, _globalOptions$option5 = _globalOptions$option.formatter, formatter = _globalOptions$option5 === void 0 ? defaultFormatter : _globalOptions$option5, _globalOptions$option6 = _globalOptions$option.pollingInterval, pollingInterval = _globalOptions$option6 === void 0 ? 0 : _globalOptions$option6, _globalOptions$option7 = _globalOptions$option.pollingWhenHidden, pollingWhenHidden = _globalOptions$option7 === void 0 ? false : _globalOptions$option7, stateMgr = _globalOptions$option.stateMgr, onFinish = _globalOptions$option.onFinish, _globalOptions$option8 = _globalOptions$option.throwOnError, throwOnError = _globalOptions$option8 === void 0 ? true : _globalOptions$option8; var service = useMemoizedFn(_service); // 组件状态控制 start var _useState = useState(() => { var _cache; return { loading: false, data: (_cache = cache[cacheKey !== null && cacheKey !== void 0 ? cacheKey : '']) !== null && _cache !== void 0 ? _cache : initialData, 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) { if (cacheKey != null && newState.data) { cache[cacheKey] = newState.data; } _setState(state => _objectSpread(_objectSpread({}, state), newState)); // _setState({ ...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; var refresh = () => Promise.resolve(); var visible = useDocumentVisibility(); // 轮询 var timer = useInterval(() => { if (visible || !pollingWhenHidden) { refresh(); } }, pollingInterval || undefined); // 发起请求 var load = useMemoizedFn( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(...args) { var ticket, _res, formattedData; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: ticket = performance.now(); _this.ticket = ticket; _this.loading = true; setState({ loading: true, error: undefined }); timer.reset(); _context.prev = 5; _context.next = 8; return service(...args); case 8: _res = _context.sent; formattedData = formatter(_res); if (!(throwOnError && formattedData instanceof Error)) { _context.next = 12; break; } throw formattedData; case 12: if (keepSuccessData && formattedData == null) { formattedData = data; } if (_this.ticket === ticket) { // 请求结果有效 _this.loading = false; setState({ params: args, loading: false, data: formattedData }); if (formattedData != null) { if (typeof onSuccess === 'function') { onSuccess(formattedData, args); } } else if (typeof onError === 'function') { // 暂时禁用 onError 的触发逻辑,数据问题不做 Error 处理 // 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 17: _context.prev = 17; _context.t0 = _context["catch"](5); console.error(_context.t0); if (_this.ticket === ticket) { _this.loading = false; if (keepSuccessData) { setState({ error: _context.t0, loading: false }); } else { setState({ error: _context.t0, loading: false, data: undefined }); } if (typeof onError === 'function') { onError(_context.t0, args); } } case 21: return _context.abrupt("return", undefined); case 22: case "end": return _context.stop(); } }, _callee, null, [[5, 17]]); }))); refresh = useMemoizedFn( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: if (!params) { _context2.next = 2; break; } return _context2.abrupt("return", load(...params)); case 2: return _context2.abrupt("return", undefined); case 3: case "end": return _context2.stop(); } }, _callee2); }))); var mutate = useMemoizedFn(data => { if (_this.unloaded) return; _setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { // @ts-expect-error data: typeof data === 'function' ? data(oldState.data) : data })); }); var cancel = useMemoizedFn(() => { _this.ticket = Date.now(); }); useEffect(() => { _this.loading = false; _this.unloaded = false; // 如果 manual === false,则需要主动加载一次 if (!manual) { load(...defaultParams); } return () => { _this.unloaded = true; }; }, []); return { loading, params, data, error, mutate, run: load, refresh, cancel }; } export default useService;