UNPKG

react-async-states-utils

Version:
239 lines (230 loc) 9.81 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('react-async-states'), require('async-states')) : typeof define === 'function' && define.amd ? define(['exports', 'react', 'react-async-states', 'async-states'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactAsyncStatesUtils = {}, global.React, global.ReactAsyncStates, global.AsyncStates)); })(this, (function (exports, React, reactAsyncStates, asyncStates) { 'use strict'; function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React); let emptyArray = []; function isFunction(fn) { return typeof fn === "function"; } const StateBoundaryContext = React__namespace.createContext(null); function StateBoundary(props) { return React__namespace.createElement(StateBoundaryImpl, Object.assign({ key: props.strategy }, props), props.children); } exports.RenderStrategy = void 0; (function (RenderStrategy) { RenderStrategy[RenderStrategy["FetchAsYouRender"] = 0] = "FetchAsYouRender"; RenderStrategy[RenderStrategy["FetchThenRender"] = 1] = "FetchThenRender"; RenderStrategy[RenderStrategy["RenderThenFetch"] = 2] = "RenderThenFetch"; })(exports.RenderStrategy || (exports.RenderStrategy = {})); let BoundarySourceContext = React__namespace.createContext(null); function BoundarySource({ source, children, }) { let parentSource = React__namespace.useContext(BoundarySourceContext); let contextValue = React__namespace.useMemo(() => ({ source, parent: parentSource, }), [source, parentSource]); return (React__namespace.createElement(BoundarySourceContext.Provider, { value: contextValue }, children)); } function StateBoundaryImpl(props) { if (props.strategy === exports.RenderStrategy.FetchThenRender) { return React__namespace.createElement(FetchThenRenderBoundary, props); } if (props.strategy === exports.RenderStrategy.FetchAsYouRender) { return React__namespace.createElement(FetchAsYouRenderBoundary, props); } return React__namespace.createElement(RenderThenFetchBoundary, props); } function inferBoundaryChildren(result, props) { if (!props.render || !result.source) { return props.children; } const { status } = result.source.getState(); return props.render[status] ? props.render[status] : props.children; } function renderChildren(children, props) { return isFunction(children) ? React__namespace.createElement(children, props) : children; } function RenderThenFetchBoundary(props) { let result = reactAsyncStates.useAsyncState(props.config, props.dependencies); const children = inferBoundaryChildren(result, props); let Context = StateBoundaryContext; return (React__namespace.createElement(BoundarySource, { source: result.source }, React__namespace.createElement(Context.Provider, { value: result }, renderChildren(children, result)))); } function FetchAsYouRenderBoundary(props) { let result = reactAsyncStates.useAsyncState(props.config, props.dependencies); result.read(); // throws const children = inferBoundaryChildren(result, props); let Context = StateBoundaryContext; return (React__namespace.createElement(BoundarySource, { source: result.source }, React__namespace.createElement(Context.Provider, { value: result }, renderChildren(children, result)))); } function FetchThenRenderInitialBoundary({ dependencies = emptyArray, result, config, }) { result.source?.patchConfig({ skipPendingStatus: true, }); React__namespace.useEffect(() => { if (config.condition !== false) { const autoRunArgs = config .autoRunArgs; if (Array.isArray(autoRunArgs)) { return result.source.run.apply(null, autoRunArgs); } return result.source.run.apply(null); } }, dependencies); return null; } function FetchThenRenderBoundary(props) { let result = reactAsyncStates.useAsyncState(props.config, props.dependencies); let Context = StateBoundaryContext; switch (result.source?.getState().status) { case reactAsyncStates.Status.pending: case reactAsyncStates.Status.initial: { return (React__namespace.createElement(FetchThenRenderInitialBoundary, { result: result, config: props.config, dependencies: props.dependencies })); } case reactAsyncStates.Status.error: case reactAsyncStates.Status.success: { const children = inferBoundaryChildren(result, props); return (React__namespace.createElement(BoundarySource, { source: result.source }, React__namespace.createElement(Context.Provider, { value: result }, renderChildren(children, result)))); } } return null; } function useCurrentState() { const ctxValue = React__namespace.useContext(StateBoundaryContext); if (ctxValue === null) { throw new Error("useCurrentState used outside StateBoundary"); } return ctxValue; } function recursivelyTraverseContextAndGetSource(ctxValue, stateKey) { if (!stateKey) { return ctxValue.source; } let currentSource = ctxValue.source; if (currentSource.key === stateKey) { return currentSource; } if (ctxValue.parent !== null) { return recursivelyTraverseContextAndGetSource(ctxValue.parent, stateKey); } throw new Error(`(${stateKey}) was not found in boundary tree`); } function useBoundary(stateKey) { const ctxValue = React__namespace.useContext(BoundarySourceContext); if (ctxValue === null) { throw new Error("useBoundary used outside StateBoundary"); } let source = recursivelyTraverseContextAndGetSource(ctxValue, stateKey); return reactAsyncStates.useAsync(source); } function run(keyOrSource, ...args) { return runImpl(keyOrSource, null, undefined, ...args); } function runLane(keyOrSource, lane, ...args) { return runImpl(keyOrSource, null, lane, ...args); } function runInContext(keyOrSource, context, ...args) { return runImpl(keyOrSource, context, undefined, ...args); } function runLaneInContext(keyOrSource, context, lane, ...args) { return runImpl(keyOrSource, context, lane, ...args); } function runImpl(keyOrSource, context, lane, ...args) { if (asyncStates.isSource(keyOrSource)) { return keyOrSource.getLane(lane).run(...args); } if (typeof keyOrSource === "string") { let instance = asyncStates.requestContext(context).get(keyOrSource); if (instance) { return instance.actions.run.apply(null, args); } } return undefined; } function extendStatus(state) { let status = state.status; switch (status) { case reactAsyncStates.Status.initial: { return { isInitial: true, isPending: false, isError: false, isAborted: false, isSuccess: false, }; } case reactAsyncStates.Status.pending: { return { isInitial: false, isPending: true, isError: false, isAborted: false, isSuccess: false, }; } case reactAsyncStates.Status.success: { return { isInitial: false, isPending: false, isError: false, isAborted: false, isSuccess: true, }; } case reactAsyncStates.Status.error: { return { isInitial: false, isPending: false, isError: true, isAborted: false, isSuccess: false, }; } } throw new Error(`Status ${status} isn't recognized!`); } function addBooleanStatus(state) { let extended = extendStatus(state); return Object.assign({}, extended, state); } let didWarnAboutDeprecation = false; if (!didWarnAboutDeprecation) { didWarnAboutDeprecation = true; console.error("[Warning] react-async-states-utils is deprecated.\n" + "It was on top of react-async-states and you can find the latest" + "version in this link: https://github.com/incepter/react-async-states/tree/d8317cbee86f119d9a3286d9f1ef648897a0484a/packages/react-async-states-utils/src ."); } exports.FetchAsYouRenderBoundary = FetchAsYouRenderBoundary; exports.FetchThenRenderBoundary = FetchThenRenderBoundary; exports.RenderThenFetchBoundary = RenderThenFetchBoundary; exports.StateBoundary = StateBoundary; exports.addBooleanStatus = addBooleanStatus; exports.run = run; exports.runInContext = runInContext; exports.runLane = runLane; exports.runLaneInContext = runLaneInContext; exports.useBoundary = useBoundary; exports.useCurrentState = useCurrentState; })); //# sourceMappingURL=react-async-states-utils.development.js.map