Skip to content

Instantly share code, notes, and snippets.

@wes5510
Last active April 23, 2020 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wes5510/b23cd0f3d6875e5c7ce3d28b01ab5a4b to your computer and use it in GitHub Desktop.
Save wes5510/b23cd0f3d6875e5c7ce3d28b01ab5a4b to your computer and use it in GitHub Desktop.
redux-routine
import { createAction } from 'redux-actions';
import { put, call } from 'redux-saga/effects';
import produce from 'immer';
import camelCase from 'lodash/camelCase';
import typeUtils from './type';
const STAGES = {
REQUEST: {
id: 'REQUEST',
loading: true,
handle: function* handle(axiosMethod, url, data) {
const res = yield call(axiosMethod, url, data);
return res;
},
},
...['SUCCESS', 'FAILURE', 'COMPLETE'].reduce((stages, stage) => {
stages[stage] = {
id: stage,
loading: false,
};
return stages;
}, {}),
};
const createStage = (namespace, baseType, id, loading, { handle }) => {
const type = typeUtils.generateTypes(
`${namespace}${typeUtils.MARK}${baseType}`,
[id],
);
return {
id,
type: type[id],
action: createAction(type[id]),
loading,
handle,
reducer: routine => callback => ({
[type[id]]: produce((draft, { payload }) => {
if (callback) {
callback(draft, { payload });
}
draft.loading[camelCase(baseType)] = routine.loading;
draft.error[camelCase(baseType)] = routine.error;
}),
}),
};
};
const createReducers = routine => (callbacks = {}) =>
Object.values(STAGES).reduce((reducers, value) => {
const id = value.id.toLowerCase();
return {
...reducers,
...routine[id].reducer(callbacks[id]),
};
}, {});
const createRoutine = (namespace, type) => {
const routine = {
loading: false,
error: null,
};
routine.id = type;
Object.values(STAGES).forEach(value => {
const stage = createStage(namespace, type, value.id, value.loading, {
handle: value.handle,
});
const id = value.id.toLowerCase();
routine[id] = {};
routine[id].reducer = stage.reducer(routine);
routine[id].type = stage.type;
routine[id].action = function* action({
payload,
axiosMethod,
url,
data,
} = {}) {
routine.loading = stage.loading;
yield put(stage.action(payload));
let ret;
if (stage.handle) {
ret = yield stage.handle(axiosMethod, url, data);
}
return ret;
};
});
routine.reducers = createReducers(routine);
routine.action = function* action(
axiosMethod,
url,
data,
{
action: {
success = routine.success.action,
request = routine.request.action,
failure = routine.failure.action,
complete = routine.complete.action,
} = {},
} = {},
) {
try {
const res = yield request({
axiosMethod,
url,
data,
});
routine.error = null;
yield success({
payload: res.data,
});
} catch (err) {
routine.error = err;
yield failure({
payload: err,
});
} finally {
yield complete();
}
};
return routine;
};
export default createRoutine;
export const getAllReducerInRoutines = routines =>
Object.keys(routines).reduce(
(reducers, key) => ({
...reducers,
...routines[key].reducers(),
}),
{},
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment