Last active
August 29, 2015 14:17
-
-
Save andrewluetgers/7768f74f9b2f2ae8730a to your computer and use it in GitHub Desktop.
Omniscient / Immstruct - forceUpdateOnState
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
/** | |
* forceUpdateOnState | |
* | |
* @param state immstruct structure | |
* @returns component mixins {componentWillMount, componentWillUpdate, componentWillUnmount} | |
* | |
* the parent component should provide to the target component | |
* a map of prop names as keys for cursors and period delimited path strings | |
* on as 'cursors' property, e.g. <div cursors={{foo: 'bar.foo'}}></div> | |
* in the above example: props.foo = state.reference(['bar', 'foo']).cursor() | |
* updates will not be top-down component will watch the path ref and | |
* force update upon any change | |
*/ | |
function forceUpdateOnState(state) { | |
return { | |
componentWillMount: function() { | |
var component = this; | |
component._cancel = []; | |
// create references, force update on change, attach cursors | |
component.references = getReferences(state, component); | |
var refs = component.references; | |
for (var name in refs) { | |
// attach cursor to instance | |
var ref = refs[name]; | |
component[name] = ref.cursor(); | |
// force update on change | |
// store cleanup function unmount | |
component._cancel.push(ref.observe('swap', function() { | |
component.forceUpdate(); | |
})); | |
} | |
}, | |
componentWillUpdate: function() { | |
// update cursors | |
var component = this, | |
refs = component.references; | |
for (var name in refs) { | |
component[name] = refs[name].cursor(); | |
} | |
}, | |
componentWillUnmount: function() { | |
// cancel observers | |
this._cancel.forEach(function(fn) {fn()}); | |
} | |
}; | |
}; | |
/** | |
* getReferences | |
* expects either a member or prop of 'cursors' such as {foo: 'foo', baz: 'bar.baz'} | |
* where the key is the name of a new member to add to the instance and | |
* the value is a space delimited path within provided state | |
* @param state immstruct structure | |
* @param component omniscient or react component instance | |
* @returns {someName: state.reference(['some', 'path']), ...} | |
*/ | |
var references = {}; | |
function getReferences(state, component) { | |
var sources = { | |
// support component defining own cursors | |
componentDefs: component.cursors, | |
// support parent defining cursors in props, will override prior cursors | |
propDefs: (component.props && component.props.cursors) | |
}, | |
refs = {}; | |
for (var source in sources) { | |
var cursorDefs = sources[source]; | |
for (var name in cursorDefs) { | |
var selector = cursorDefs[name]; | |
// in conjunction with forceUpdateOnState will attache references and cursors to the instance | |
// it will also register reference observers that will force render and refresh cursors upon change | |
references[selector] = refs[name] = references[selector] || state.reference(selector.split(".")); | |
} | |
} | |
return refs; | |
} | |
module.exports = forceUpdateOnState; |
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
// basic usage of forceUpdateOnState | |
var React = require('react'), | |
component = require('omniscient'), | |
immstruct = require('immstruct') | |
forceUpdateOnState = require("./forceUpdateOnState"); | |
var state = immstruct({query: {term: 'test', size: 100}}); | |
var mixins = forceUpdateOnState(state); | |
var Thing1 = component("Thing1", [{ | |
// can define cursors within the component | |
// this will create a cursor and put it on this.term | |
cursors: { | |
term: 'query.term' | |
} | |
}, mixins], function() { | |
// can also define from parent level (does not support both) | |
// do not pass parent's cursors down to children | |
// insted define them via the cursors object | |
return ( | |
<div> | |
{this.term.deref()} | |
<Thing2 cursors={{size: 'query.size'}} /> | |
</div> | |
); | |
}); | |
var Thing2 = component("Thing2", [mixins], function() { | |
return ( | |
<div>this.size.deref()</div | |
); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment