UNPKG

react-async

Version:

React component for declarative promise resolution and data fetching

987 lines (854 loc) 29.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } /* istanbul ignore file */ /** * Universal global scope object. In the browser this is `self`, in Node.js and React Native it's `global`. * This file is excluded from coverage reporting because these globals are environment-specific so we can't test them all. */ const globalScope = (() => { if (typeof self === "object" && self.self === self) return self; if (typeof global === "object" && global.global === global) return global; if (typeof global === "object" && global.GLOBAL === global) return global; return {}; // fallback that relies on imported modules to be singletons })(); /** * Globally available object used to connect the DevTools to all React Async instances. */ globalScope.__REACT_ASYNC__ = globalScope.__REACT_ASYNC__ || {}; const noop = () => {}; class MockAbortController { constructor() { this.abort = noop; this.signal = {}; } } let PropTypes; try { PropTypes = require("prop-types"); } catch (e) {} const childrenFn = PropTypes && PropTypes.oneOfType([PropTypes.node, PropTypes.func]); const stateObject = PropTypes && PropTypes.shape({ initialValue: PropTypes.any, data: PropTypes.any, error: PropTypes.instanceOf(Error), value: PropTypes.any, startedAt: PropTypes.instanceOf(Date), finishedAt: PropTypes.instanceOf(Date), status: PropTypes.oneOf(["initial", "pending", "fulfilled", "rejected"]), isInitial: PropTypes.bool, isPending: PropTypes.bool, isLoading: PropTypes.bool, isFulfilled: PropTypes.bool, isResolved: PropTypes.bool, isRejected: PropTypes.bool, isSettled: PropTypes.bool, counter: PropTypes.number, promise: PropTypes.instanceOf(Promise), run: PropTypes.func, reload: PropTypes.func, cancel: PropTypes.func, setData: PropTypes.func, setError: PropTypes.func }); var propTypes = PropTypes && { Async: { children: childrenFn, promise: PropTypes.instanceOf(Promise), promiseFn: PropTypes.func, deferFn: PropTypes.func, watch: PropTypes.any, watchFn: PropTypes.func, initialValue: PropTypes.any, onResolve: PropTypes.func, onReject: PropTypes.func, reducer: PropTypes.func, dispatcher: PropTypes.func, debugLabel: PropTypes.string, suspense: PropTypes.bool }, Initial: { children: childrenFn, state: stateObject.isRequired, persist: PropTypes.bool }, Pending: { children: childrenFn, state: stateObject.isRequired, initial: PropTypes.bool }, Fulfilled: { children: childrenFn, state: stateObject.isRequired, persist: PropTypes.bool }, Rejected: { children: childrenFn, state: stateObject.isRequired, persist: PropTypes.bool }, Settled: { children: childrenFn, state: stateObject.isRequired, persist: PropTypes.bool } }; const renderFn = (children, ...args) => { if (typeof children === "function") { const render = children; return render(...args); } return children; }; /** * Renders only when no promise has started or completed yet. * * @prop {Function|Node} children Function (passing state) or React node * @prop {Object} state React Async state object * @prop {boolean} persist Show until we have data, even while pending (loading) or when an error occurred */ const IfInitial = ({ children, persist, state = {} }) => React__default.createElement(React__default.Fragment, null, state.isInitial || persist && !state.data ? renderFn(children, state) : null); /** * Renders only while pending (promise is loading). * * @prop {Function|Node} children Function (passing state) or React node * @prop {Object} state React Async state object * @prop {boolean} initial Show only on initial load (data is undefined) */ const IfPending = ({ children, initial, state = {} }) => React__default.createElement(React__default.Fragment, null, state.isPending && (!initial || !state.value) ? renderFn(children, state) : null); /** * Renders only when promise is resolved. * * @prop {Function|Node} children Function (passing data and state) or React node * @prop {Object} state React Async state object * @prop {boolean} persist Show old data while pending (promise is loading) */ const IfFulfilled = ({ children, persist, state = {} }) => React__default.createElement(React__default.Fragment, null, state.isFulfilled || persist && state.data ? renderFn(children, state.data, state) : null); /** * Renders only when promise is rejected. * * @prop {Function|Node} children Function (passing error and state) or React node * @prop {Object} state React Async state object * @prop {boolean} persist Show old error while pending (promise is loading) */ const IfRejected = ({ children, persist, state = {} }) => React__default.createElement(React__default.Fragment, null, state.isRejected || persist && state.error ? renderFn(children, state.error, state) : null); /** * Renders only when promise is fulfilled or rejected. * * @prop {Function|Node} children Function (passing state) or React node * @prop {Object} state React Async state object * @prop {boolean} persist Show old data or error while pending (promise is loading) */ const IfSettled = ({ children, persist, state = {} }) => React__default.createElement(React__default.Fragment, null, state.isSettled || persist && state.value ? renderFn(children, state) : null); if (propTypes) { IfInitial.propTypes = propTypes.Initial; IfPending.propTypes = propTypes.Pending; IfFulfilled.propTypes = propTypes.Fulfilled; IfRejected.propTypes = propTypes.Rejected; IfSettled.propTypes = propTypes.Settled; } (function (StatusTypes) { StatusTypes["initial"] = "initial"; StatusTypes["pending"] = "pending"; StatusTypes["fulfilled"] = "fulfilled"; StatusTypes["rejected"] = "rejected"; })(exports.StatusTypes || (exports.StatusTypes = {})); const getInitialStatus = (value, promise) => { if (value instanceof Error) return exports.StatusTypes.rejected; if (value !== undefined) return exports.StatusTypes.fulfilled; if (promise) return exports.StatusTypes.pending; return exports.StatusTypes.initial; }; const getIdleStatus = value => { if (value instanceof Error) return exports.StatusTypes.rejected; if (value !== undefined) return exports.StatusTypes.fulfilled; return exports.StatusTypes.initial; }; const getStatusProps = status => ({ status, isInitial: status === exports.StatusTypes.initial, isPending: status === exports.StatusTypes.pending, isLoading: status === exports.StatusTypes.pending, isFulfilled: status === exports.StatusTypes.fulfilled, isResolved: status === exports.StatusTypes.fulfilled, isRejected: status === exports.StatusTypes.rejected, isSettled: status === exports.StatusTypes.fulfilled || status === exports.StatusTypes.rejected }); // The way NeverSettle extends from Promise is complicated, but can't be done differently because Babel doesn't support // extending built-in classes. See https://babeljs.io/docs/en/caveats/#classes const NeverSettle = function () {}; /* istanbul ignore next */ if (Object.setPrototypeOf) { Object.setPrototypeOf(NeverSettle, Promise); } else { NeverSettle.__proto__ = Promise; } NeverSettle.prototype = Object.assign(Object.create(Promise.prototype), { finally() { return this; }, catch() { return this; }, then() { return this; } }); const neverSettle = new NeverSettle(); (function (ActionTypes) { ActionTypes["start"] = "start"; ActionTypes["cancel"] = "cancel"; ActionTypes["fulfill"] = "fulfill"; ActionTypes["reject"] = "reject"; })(exports.ActionTypes || (exports.ActionTypes = {})); const init = ({ initialValue, promise, promiseFn }) => _objectSpread2({ initialValue, data: initialValue instanceof Error ? undefined : initialValue, error: initialValue instanceof Error ? initialValue : undefined, value: initialValue, startedAt: promise || promiseFn ? new Date() : undefined, finishedAt: initialValue ? new Date() : undefined }, getStatusProps(getInitialStatus(initialValue, promise || promiseFn)), { counter: 0, promise: neverSettle }); const reducer = (state, action) => { switch (action.type) { case exports.ActionTypes.start: return _objectSpread2({}, state, { startedAt: new Date(), finishedAt: undefined }, getStatusProps(exports.StatusTypes.pending), { counter: action.meta.counter, promise: action.meta.promise }); case exports.ActionTypes.cancel: return _objectSpread2({}, state, { startedAt: undefined, finishedAt: undefined }, getStatusProps(getIdleStatus(state.error || state.data)), { counter: action.meta.counter, promise: action.meta.promise }); case exports.ActionTypes.fulfill: return _objectSpread2({}, state, { data: action.payload, value: action.payload, error: undefined, finishedAt: new Date() }, getStatusProps(exports.StatusTypes.fulfilled), { promise: action.meta.promise }); case exports.ActionTypes.reject: return _objectSpread2({}, state, { error: action.payload, value: action.payload, finishedAt: new Date() }, getStatusProps(exports.StatusTypes.rejected), { promise: action.meta.promise }); default: return state; } }; const dispatchMiddleware = dispatch => (action, ...args) => { dispatch(action, ...args); if (action.type === exports.ActionTypes.start && typeof action.payload === "function") { action.payload(); } }; class Async extends React__default.Component {} /** * createInstance allows you to create instances of Async that are bound to a specific promise. * A unique instance also uses its own React context for better nesting capability. */ function createInstance(defaultOptions = {}, displayName = "Async") { const { Consumer: UnguardedConsumer, Provider } = React__default.createContext(undefined); function Consumer({ children }) { return React__default.createElement(UnguardedConsumer, null, value => { if (!value) { throw new Error("this component should only be used within an associated <Async> component!"); } return children(value); }); } class Async extends React__default.Component { constructor(props) { super(props); this.mounted = false; this.counter = 0; this.args = []; this.promise = neverSettle; this.abortController = new MockAbortController(); this.start = this.start.bind(this); this.load = this.load.bind(this); this.run = this.run.bind(this); this.cancel = this.cancel.bind(this); this.onResolve = this.onResolve.bind(this); this.onReject = this.onReject.bind(this); this.setData = this.setData.bind(this); this.setError = this.setError.bind(this); const promise = props.promise; const promiseFn = props.promiseFn || defaultOptions.promiseFn; const initialValue = props.initialValue || defaultOptions.initialValue; this.state = _objectSpread2({}, init({ initialValue, promise, promiseFn }), { cancel: this.cancel, run: this.run, reload: () => { this.load(); this.run(...this.args); }, setData: this.setData, setError: this.setError }); this.debugLabel = props.debugLabel || defaultOptions.debugLabel; const { devToolsDispatcher } = globalScope.__REACT_ASYNC__; const _reducer = props.reducer || defaultOptions.reducer; const _dispatcher = props.dispatcher || defaultOptions.dispatcher || devToolsDispatcher; const reducer$1 = _reducer ? (state, action) => _reducer(state, action, reducer) : reducer; const dispatch = dispatchMiddleware((action, callback) => { this.setState(state => reducer$1(state, action), callback); }); this.dispatch = _dispatcher ? action => _dispatcher(action, dispatch, props) : dispatch; } componentDidMount() { this.mounted = true; if (this.props.promise || !this.state.initialValue) { this.load(); } } componentDidUpdate(prevProps) { const { watch, watchFn = defaultOptions.watchFn, promise, promiseFn } = this.props; if (watch !== prevProps.watch) { if (this.counter) this.cancel(); return this.load(); } if (watchFn && watchFn(_objectSpread2({}, defaultOptions, {}, this.props), _objectSpread2({}, defaultOptions, {}, prevProps))) { if (this.counter) this.cancel(); return this.load(); } if (promise !== prevProps.promise) { if (this.counter) this.cancel(); if (promise) return this.load(); } if (promiseFn !== prevProps.promiseFn) { if (this.counter) this.cancel(); if (promiseFn) return this.load(); } } componentWillUnmount() { this.cancel(); this.mounted = false; } getMeta(meta) { return _objectSpread2({ counter: this.counter, promise: this.promise, debugLabel: this.debugLabel }, meta); } start(promiseFn) { if ("AbortController" in globalScope) { this.abortController.abort(); this.abortController = new globalScope.AbortController(); } this.counter++; return this.promise = new Promise((resolve, reject) => { if (!this.mounted) return; const executor = () => promiseFn().then(resolve, reject); this.dispatch({ type: exports.ActionTypes.start, payload: executor, meta: this.getMeta() }); }); } load() { const promise = this.props.promise; const promiseFn = this.props.promiseFn || defaultOptions.promiseFn; if (promise) { this.start(() => promise).then(this.onResolve(this.counter)).catch(this.onReject(this.counter)); } else if (promiseFn) { const props = _objectSpread2({}, defaultOptions, {}, this.props); this.start(() => promiseFn(props, this.abortController)).then(this.onResolve(this.counter)).catch(this.onReject(this.counter)); } } run(...args) { const deferFn = this.props.deferFn || defaultOptions.deferFn; if (deferFn) { this.args = args; const props = _objectSpread2({}, defaultOptions, {}, this.props); return this.start(() => deferFn(args, props, this.abortController)).then(this.onResolve(this.counter), this.onReject(this.counter)); } } cancel() { const onCancel = this.props.onCancel || defaultOptions.onCancel; onCancel && onCancel(); this.counter++; this.abortController.abort(); this.mounted && this.dispatch({ type: exports.ActionTypes.cancel, meta: this.getMeta() }); } onResolve(counter) { return data => { if (this.counter === counter) { const onResolve = this.props.onResolve || defaultOptions.onResolve; this.setData(data, () => onResolve && onResolve(data)); } return data; }; } onReject(counter) { return error => { if (this.counter === counter) { const onReject = this.props.onReject || defaultOptions.onReject; this.setError(error, () => onReject && onReject(error)); } return error; }; } setData(data, callback) { this.mounted && this.dispatch({ type: exports.ActionTypes.fulfill, payload: data, meta: this.getMeta() }, callback); return data; } setError(error, callback) { this.mounted && this.dispatch({ type: exports.ActionTypes.reject, payload: error, error: true, meta: this.getMeta() }, callback); return error; } render() { const { children, suspense } = this.props; if (suspense && this.state.isPending && this.promise !== neverSettle) { // Rely on Suspense to handle the loading state throw this.promise; } if (typeof children === "function") { const render = children; return React__default.createElement(Provider, { value: this.state }, render(this.state)); } if (children !== undefined && children !== null) { return React__default.createElement(Provider, { value: this.state }, children); } return null; } } if (propTypes) Async.propTypes = propTypes.Async; const AsyncInitial = props => React__default.createElement(Consumer, null, st => React__default.createElement(IfInitial, Object.assign({}, props, { state: st }))); const AsyncPending = props => React__default.createElement(Consumer, null, st => React__default.createElement(IfPending, Object.assign({}, props, { state: st }))); const AsyncFulfilled = props => React__default.createElement(Consumer, null, st => React__default.createElement(IfFulfilled, Object.assign({}, props, { state: st }))); const AsyncRejected = props => React__default.createElement(Consumer, null, st => React__default.createElement(IfRejected, Object.assign({}, props, { state: st }))); const AsyncSettled = props => React__default.createElement(Consumer, null, st => React__default.createElement(IfSettled, Object.assign({}, props, { state: st }))); AsyncInitial.displayName = `${displayName}.Initial`; AsyncPending.displayName = `${displayName}.Pending`; AsyncFulfilled.displayName = `${displayName}.Fulfilled`; AsyncRejected.displayName = `${displayName}.Rejected`; AsyncSettled.displayName = `${displayName}.Settled`; return Object.assign(Async, { displayName: displayName, Initial: AsyncInitial, Pending: AsyncPending, Loading: AsyncPending, Fulfilled: AsyncFulfilled, Resolved: AsyncFulfilled, Rejected: AsyncRejected, Settled: AsyncSettled }); } var Async$1 = createInstance(); function useAsync(arg1, arg2) { const options = typeof arg1 === "function" ? _objectSpread2({}, arg2, { promiseFn: arg1 }) : arg1; const counter = React.useRef(0); const isMounted = React.useRef(true); const lastArgs = React.useRef(undefined); const lastOptions = React.useRef(options); const lastPromise = React.useRef(neverSettle); const abortController = React.useRef(new MockAbortController()); const { devToolsDispatcher } = globalScope.__REACT_ASYNC__; const { reducer: reducer$1, dispatcher = devToolsDispatcher } = options; const [state, _dispatch] = React.useReducer(reducer$1 ? (state, action) => reducer$1(state, action, reducer) : reducer, options, init); const dispatch = React.useCallback(dispatcher ? action => dispatcher(action, dispatchMiddleware(_dispatch), lastOptions.current) : dispatchMiddleware(_dispatch), [dispatcher]); const { debugLabel } = options; const getMeta = React.useCallback(meta => _objectSpread2({ counter: counter.current, promise: lastPromise.current, debugLabel }, meta), [debugLabel]); const setData = React.useCallback((data, callback = noop) => { if (isMounted.current) { dispatch({ type: exports.ActionTypes.fulfill, payload: data, meta: getMeta() }); callback(); } return data; }, [dispatch, getMeta]); const setError = React.useCallback((error, callback = noop) => { if (isMounted.current) { dispatch({ type: exports.ActionTypes.reject, payload: error, error: true, meta: getMeta() }); callback(); } return error; }, [dispatch, getMeta]); const { onResolve, onReject } = options; const handleResolve = React.useCallback(count => data => count === counter.current && setData(data, () => onResolve && onResolve(data)), [setData, onResolve]); const handleReject = React.useCallback(count => err => count === counter.current && setError(err, () => onReject && onReject(err)), [setError, onReject]); const start = React.useCallback(promiseFn => { if ("AbortController" in globalScope) { abortController.current.abort(); abortController.current = new globalScope.AbortController(); } counter.current++; return lastPromise.current = new Promise((resolve, reject) => { if (!isMounted.current) return; const executor = () => promiseFn().then(resolve, reject); dispatch({ type: exports.ActionTypes.start, payload: executor, meta: getMeta() }); }); }, [dispatch, getMeta]); const { promise, promiseFn, initialValue } = options; const load = React.useCallback(() => { const isPreInitialized = initialValue && counter.current === 0; if (promise) { start(() => promise).then(handleResolve(counter.current)).catch(handleReject(counter.current)); } else if (promiseFn && !isPreInitialized) { start(() => promiseFn(lastOptions.current, abortController.current)).then(handleResolve(counter.current)).catch(handleReject(counter.current)); } }, [start, promise, promiseFn, initialValue, handleResolve, handleReject]); const { deferFn } = options; const run = React.useCallback((...args) => { if (deferFn) { lastArgs.current = args; start(() => deferFn(args, lastOptions.current, abortController.current)).then(handleResolve(counter.current)).catch(handleReject(counter.current)); } }, [start, deferFn, handleResolve, handleReject]); const reload = React.useCallback(() => { lastArgs.current ? run(...lastArgs.current) : load(); }, [run, load]); const { onCancel } = options; const cancel = React.useCallback(() => { onCancel && onCancel(); counter.current++; abortController.current.abort(); isMounted.current && dispatch({ type: exports.ActionTypes.cancel, meta: getMeta() }); }, [onCancel, dispatch, getMeta]); /* These effects should only be triggered on changes to specific props */ /* eslint-disable react-hooks/exhaustive-deps */ const { watch, watchFn } = options; React.useEffect(() => { if (watchFn && lastOptions.current && watchFn(options, lastOptions.current)) { lastOptions.current = options; load(); } }); React.useEffect(() => { lastOptions.current = options; }, [options]); React.useEffect(() => { if (counter.current) cancel(); if (promise || promiseFn) load(); }, [promise, promiseFn, watch]); React.useEffect(() => () => { isMounted.current = false; }, []); React.useEffect(() => () => cancel(), []); /* eslint-enable react-hooks/exhaustive-deps */ React.useDebugValue(state, ({ status }) => `[${counter.current}] ${status}`); if (options.suspense && state.isPending && lastPromise.current !== neverSettle) { // Rely on Suspense to handle the loading state throw lastPromise.current; } return React.useMemo(() => _objectSpread2({}, state, { run, reload, cancel, setData, setError }), [state, run, reload, cancel, setData, setError]); } class FetchError extends Error { constructor(response) { super(`${response.status} ${response.statusText}`); this.response = response; /* istanbul ignore next */ if (Object.setPrototypeOf) { // Not available in IE 10, but can be polyfilled Object.setPrototypeOf(this, FetchError.prototype); } } } const parseResponse = (accept, json) => res => { if (!res.ok) return Promise.reject(new FetchError(res)); if (typeof json === "boolean") return json ? res.json() : res; return accept === "application/json" ? res.json() : res; }; function isEvent(e) { return typeof e === "object" && "preventDefault" in e; } /** * * @param {RequestInfo} resource * @param {RequestInit} init * @param {FetchOptions} options * @returns {AsyncState<T, FetchRun<T>>} */ function useAsyncFetch(resource, init, _ref = {}) { let { defer, json } = _ref, options = _objectWithoutProperties(_ref, ["defer", "json"]); const method = resource.method || init && init.method; const headers = resource.headers || init && init.headers || {}; const accept = headers["Accept"] || headers["accept"] || headers.get && headers.get("accept"); const doFetch = (input, init) => globalScope.fetch(input, init).then(parseResponse(accept, json)); const isDefer = typeof defer === "boolean" ? defer : ["POST", "PUT", "PATCH", "DELETE"].indexOf(method) !== -1; const fn = isDefer ? "deferFn" : "promiseFn"; const identity = JSON.stringify({ resource, init, isDefer }); const promiseFn = React.useCallback((_, { signal }) => { return doFetch(resource, _objectSpread2({ signal }, init)); }, [identity] // eslint-disable-line react-hooks/exhaustive-deps ); const deferFn = React.useCallback(function ([override], _, { signal }) { if (!override || isEvent(override)) { return doFetch(resource, _objectSpread2({ signal }, init)); } if (typeof override === "function") { const _override = override(_objectSpread2({ resource, signal }, init)), { resource: runResource } = _override, runInit = _objectWithoutProperties(_override, ["resource"]); return doFetch(runResource || resource, _objectSpread2({ signal }, runInit)); } const { resource: runResource } = override, runInit = _objectWithoutProperties(override, ["resource"]); return doFetch(runResource || resource, _objectSpread2({ signal }, init, {}, runInit)); }, [identity] // eslint-disable-line react-hooks/exhaustive-deps ); const state = useAsync(_objectSpread2({}, options, { [fn]: isDefer ? deferFn : promiseFn })); React.useDebugValue(state, ({ counter, status }) => `[${counter}] ${status}`); return state; } const unsupported = () => { throw new Error("useAsync requires React v16.8 or up. Upgrade your React version or use the <Async> component instead."); }; var useAsync$1 = React.useEffect ? useAsync : unsupported; const useFetch = React.useEffect ? useAsyncFetch : unsupported; exports.Async = Async$1; exports.FetchError = FetchError; exports.IfFulfilled = IfFulfilled; exports.IfInitial = IfInitial; exports.IfPending = IfPending; exports.IfRejected = IfRejected; exports.IfSettled = IfSettled; exports.createInstance = createInstance; exports.default = Async$1; exports.dispatchMiddleware = dispatchMiddleware; exports.globalScope = globalScope; exports.init = init; exports.neverSettle = neverSettle; exports.reducer = reducer; exports.useAsync = useAsync$1; exports.useFetch = useFetch; //# sourceMappingURL=index.js.map