kilto
Version:
A state management system with easy async and low boilerplate.
68 lines (54 loc) • 1.8 kB
JavaScript
;
import isPromise from './util/isPromise';
// TODO: middleware support
export default function createStore(initialState) {
let state = initialState;
const subscribers = [];
const getState = () => state;
const updateState = (newState) => {
if (newState === state) return state;
state = newState;
subscribers.forEach((subscriber) => {
subscriber(state);
});
return state;
};
const unsubscribe = (cb) => {
const i = subscribers.indexOf(cb);
if (i > -1) {
subscribers.splice(i, 1);
}
};
const subscribe = (cb) => {
subscribers.push(cb);
return () => unsubscribe(cb);
};
const dispatch = (actionsArg, ...args) => {
if (actionsArg === null || actionsArg === undefined) {
throw new TypeError('The first argument of dispatch must be a function or array.');
}
const actions = Array.isArray(actionsArg) ? actionsArg : [actionsArg];
const action = actions[0];
const result = action(state, ...args);
if (actions.length > 1) {
if (isPromise(result)) {
result.then((asyncResult) => {
dispatch(actions.slice(1), asyncResult, ...args);
}).catch((error) => {
console.error('Error encountered in action promise. Action was ignored.', error, action.name);
});
}
else {
dispatch(actions.slice(1), result, ...args);
}
}
else {
if (isPromise(result) || result === null || result === undefined) {
throw new Error(`The last function in an action must be a syncrounous pure function of state (not a Promise)! Offending action is ${action.name}.`);
}
updateState(result);
}
};
const reset = () => updateState(initialState);
return { getState, subscribe, reset, dispatch };
}