Skip to content

Instantly share code, notes, and snippets.

@luwes
Created December 26, 2017 04:59
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 luwes/569d8846b18e6a5406e1a218f5244b4d to your computer and use it in GitHub Desktop.
Save luwes/569d8846b18e6a5406e1a218f5244b4d to your computer and use it in GitHub Desktop.
Experiment to add selectors to state as getters
/**
The selectors would be a map e.g.
const selectors = {
ui: {
getDoubleBurgers: (state) => state.ui.burger + state.ui.burger
}
}
*/
export default function proxySelectors(reducer, selectors) {
const map = generateSelectorsMap(selectors);
return (state = {}, action) => {
return setSelectors(state, reducer(state, action), map);
};
}
function setSelectors(prevState, nextState, map) {
for (const path in map) {
const selectors = map[path];
const slice = get(nextState, path);
if (slice) {
for (const name in selectors) {
const selector = selectors[name];
if (!Object.getOwnPropertyDescriptor(slice, name)) {
Object.defineProperty(slice, name, {
get: () => selector(nextState)
});
}
}
}
}
return nextState;
}
function get(obj, path, defaultValue) {
const keys = path.split('.');
for (let i = 0; i < keys.length; i++) {
if (typeof obj === 'undefined') {
return defaultValue;
}
obj = obj[keys[i]];
}
return obj;
}
function generateSelectorsMap(obj, keys = []) {
return Object.keys(obj).reduce((acc, key) => {
if (typeof obj[key] === 'function' && key !== 'default') {
const path = keys.join('.');
const pathObj = acc[path] || {};
pathObj[key] = obj[key];
return Object.assign(acc, { [path]: pathObj });
}
if (typeof obj[key] === 'object') {
return Object.assign(acc, generateSelectorsMap(obj[key], keys.concat(key)));
}
return acc;
}, {});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment