UNPKG

react-async

Version:

React component for declarative promise resolution and data fetching

93 lines (92 loc) 3.22 kB
import { getInitialStatus, getIdleStatus, getStatusProps, StatusTypes } from "./status"; // This exists to make sure we don't hold any references to user-provided functions // 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; }, }); export const neverSettle = new NeverSettle(); export var ActionTypes; (function (ActionTypes) { ActionTypes["start"] = "start"; ActionTypes["cancel"] = "cancel"; ActionTypes["fulfill"] = "fulfill"; ActionTypes["reject"] = "reject"; })(ActionTypes || (ActionTypes = {})); export const init = ({ initialValue, promise, promiseFn, }) => ({ 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, }); export const reducer = (state, action) => { switch (action.type) { case ActionTypes.start: return { ...state, startedAt: new Date(), finishedAt: undefined, ...getStatusProps(StatusTypes.pending), counter: action.meta.counter, promise: action.meta.promise, }; case ActionTypes.cancel: return { ...state, startedAt: undefined, finishedAt: undefined, ...getStatusProps(getIdleStatus(state.error || state.data)), counter: action.meta.counter, promise: action.meta.promise, }; case ActionTypes.fulfill: return { ...state, data: action.payload, value: action.payload, error: undefined, finishedAt: new Date(), ...getStatusProps(StatusTypes.fulfilled), promise: action.meta.promise, }; case ActionTypes.reject: return { ...state, error: action.payload, value: action.payload, finishedAt: new Date(), ...getStatusProps(StatusTypes.rejected), promise: action.meta.promise, }; default: return state; } }; export const dispatchMiddleware = (dispatch) => (action, ...args) => { dispatch(action, ...args); if (action.type === ActionTypes.start && typeof action.payload === "function") { action.payload(); } };