Skip to content

Instantly share code, notes, and snippets.

@nckcol
Created December 16, 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 nckcol/326791774269dadc6eefcc53a1f15747 to your computer and use it in GitHub Desktop.
Save nckcol/326791774269dadc6eefcc53a1f15747 to your computer and use it in GitHub Desktop.
/*
State example:
*/
const example = {
'section_id=1&geo_id=1': {
filters: {
loadingState: 'loaded',
config: {...}
},
sorting: {
loadingState: 'loading',
config: null
}
},
'section_id=2&geo_id=1: {
map: {
loadingState: 'loaded',
config: {...}
}
},
'section_id=2&geo_id=1: {
map: {
loadingState: 'not_asked',
config: null
}
}
};
/* example end */
const idString = (id) => {
if (id == null) {
return 'null';
}
return id.toString();
};
const createConfigKey = (sectionId, geoId) =>
`section_id=${idString(sectionId)}&geo_id=${idString(geoId)}`;
const mapTable = (table, mapper) =>
Object.entries(table)
.map(([key, value], index) => [key, mapper(value, key, index)])
.map(([key, value]) => ({ [key]: value }))
.reduce((objectA, objectB) => Object.assign(objectA, objectB), {});
const fieldReducerBuilder = field =>
createReducer(
{
loadingState: LOADING_STATE.NOT_ASKED,
config: null,
},
{
[REQUEST]: () => ({
loadingState: LOADING_STATE.LOADING,
config: null,
}),
[RESPONSE]: (state, { config }, error) =>
(error
? {
loadingState: LOADING_STATE.FAILED,
config: null,
}
: {
loadingState: LOADING_STATE.LOADED,
config: config[field],
}),
},
);
function itemReducer(state = {}, action) {
switch (action.type) {
case REQUEST:
case RESPONSE: {
const { fields } = action.payload;
if (!fields.length) {
return mapTable(state, (fieldState, field) =>
fieldReducerBuilder(field)(fieldState, action),
);
}
// create new fields, if they are not exist
const emptyFields = fields
.map(field => ({ [field]: undefined }))
.reduce((objectA, objectB) => Object.assign(objectA, objectB), {});
return mapTable(
{
...emptyFields,
...state,
},
(fieldState, field) => fieldReducerBuilder(field)(fieldState, action),
);
}
default:
return mapTable(state, (fieldState, field) => fieldReducerBuilder(field)(fieldState, action));
}
}
function tableReducer(state = {}, action) {
switch (action.type) {
case REQUEST:
case RESPONSE: {
const { sectionId, geoId } = action.payload;
const key = createConfigKey(sectionId, geoId);
return mapTable(
{
// create new key, if it is not exist
[key]: undefined,
...state,
},
value => itemReducer(value, action),
);
}
default:
return mapTable(state, value => itemReducer(value, action));
}
}
export default tableReducer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment