Last active
December 31, 2016 06:10
-
-
Save blainekasten/20c1512c2d6fe87290f762395646ed2b to your computer and use it in GitHub Desktop.
Makes paths observable to state locations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This is just a concept to use ES6 Proxies for a flux-like implementation where | |
* components are observers of state nodes. Using Proxie setters, when the specific | |
* state node is mutated, the components who observe that are re-rendered on the spot. | |
* | |
* likely missing some logic, just a concept | |
*/ | |
import state from 'state'; | |
import { componentToStateMap, pathMapper } from 'pathMapperProxy'; | |
function observe(getProperties) { | |
const proxy = new Proxy(state, pathMapper); | |
const properties = getProperties(proxy); | |
const fromState = {}; | |
Reflect.ownKeys(properties).forEach(k => { | |
// get the actual value from the state | |
fromState[k] = state[r[k].getPath]; // not exactly right, but general idea. | |
// push the observing component into a WeakMap ideally where path | |
// correlates to components. | |
// when the state is mutated, it iterates over that paths components | |
// and calls .forceUpdate() | |
componentToStateMap[r[k].getPath].push(ObservingComponent); | |
}); | |
// functional-programming style | |
return (Component) => { | |
// a class so we get `.forceUpdate()` | |
// yes I realize this class is not in scope for the above `.push`, it's just an example | |
return class ObservingComponent extends React.Component { | |
render() { | |
return <Component {...props} {...fromState} />; | |
} | |
} | |
} | |
} | |
// Public API | |
observe(s => ({ | |
foo: s.foo.bar, | |
baz: s.foo.baz[2], | |
}))(MyComponent) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// proxy does things like this: | |
// state.foo.bar => ".foo.bar" | |
let path = ''; | |
export const componentToStateMap = {}; // should be a WeakMap | |
export const pathMapper = { | |
// this getter is the fancy way of building a path as you read | |
get(obj, reqNode) { | |
if (reqNode === 'getPath') { | |
let pathCopy = path; | |
path = '' | |
return pathCopy; | |
} | |
let objNode = obj[reqNode]; | |
if (Array.isArray(obj)) { | |
path += `[${reqNode}]`; | |
} else { | |
path += `.${reqNode}`; | |
} | |
if (typeof objNode !== 'object') { | |
const finalResults = {getPath: path}; | |
path = ''; | |
return finalResults; | |
} | |
return new Proxy(obj[reqNode], pathMapper); | |
}, | |
// this is sort of the magic, | |
// when a value is set, we have also built the path along the way | |
// since the getter is triggered too. | |
// with the path we can use our map to iterate and call forceUpdate | |
set(node, value) { | |
node = value; | |
componentToStateMap[path].forEach(comp => comp.forceUpdate()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// example state | |
export default { | |
foo: { | |
bar: 'yeah', | |
baz: [ | |
{ far: [1]}, | |
1, | |
2 | |
], | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment