react-async
Version:
React component for declarative promise resolution and data fetching
93 lines (92 loc) • 3.22 kB
JavaScript
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();
}
};