From f3453b01b04910e3a4d2585b33f5eb355c34b7fb Mon Sep 17 00:00:00 2001 From: Vlad Balin Date: Tue, 27 Oct 2015 00:52:16 -0400 Subject: [PATCH 1/3] example with fresh design --- examples/stores.md | 126 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 examples/stores.md diff --git a/examples/stores.md b/examples/stores.md new file mode 100644 index 0000000..09efeaf --- /dev/null +++ b/examples/stores.md @@ -0,0 +1,126 @@ +- stores are needed to resolve id references in models. This is kind of `database`. +- there's one default global store. +- they may be used to bulk or lazy data loading when UI updates not needed. No other use cases. +- stores must be defined on the top level, and elements must be passed down as props. +- some components may borrow store elements to its model attributes. Rare pattern. +- some components may add or override upper store. Rare pattern. +- components model may be defined as store, to be included in lookup algorithm. + it won't be visible to its children. Very rare pattern. + +```javascript +var Top = React.createClass({ + // members fetched on first access, no updates on changes + useStore : LazyStore.defaults({ + users : User.Collection, + roles : Role.Collection, + channelSets : ChannelSet.Collection + _api : MasterStore.take( api ).merge() // create proxy native props accessors + }), + + attributes : { + role : Role.from( 'roles' ) // render on instance replace + }, + + render(){ + var store = this.getStore(), + model = this.model; + + return ( +
+ model.role = role } /> + +
+ ); + } +}); + +var Roles = React.createClass({ + // render only if prop values change + isolated : true, // same as mixins : [ PureRenderMixin ], + + attributes : { + roles : Collection.take( 'props.collection' ), // -> this._owner.props.collection + selected : Role.from( 'roles' ).onChange( 'props.selected' ) // -> + /* install hook .set( function( value ){ + this._owner.props.selected( value ); + return value; + }) */ + }, + + render(){ + var model = this.model; + return (...); + } +}); + +var Role = React.createClass({ + updateOnProps : 'model', + + render(){ + var model = this.model; + return ( + + + { this.tabs.map( ( x, i ) => +
+ ... +
+ )} +
+ + + { this.tabs.map( x => ... )} + +
); + }, + + tabs : [{ + Title : 'Permissions', + Component : Permissions + },{ + Title : 'Roles', + Component : UserRoles + }] +}); + + + + + +var Top = React.createClass({ + // when `useStore` is function + getChildContext : function(){ + return { store : this.getStore() }; + }, + + childContextTypes : { + store : React.PropTypes.object // mix it in + }, + + // When `model` or `useStore` + contextTypes : { + store : React.PropTypes.object // mix it in + }, + + getStore : function(){ + var upperStore = this.context.store; + + if( !this._store ){ + if( typeof this.useStore === 'function' ){ + this._store = new this.useStore(); + if( upperStore ) this._store._owner = upperStore; + } + else{ + this._store = upperStore || Nested.store; + } + } + + return this._store; + }, + + render(){ + return (); + } +}); + +``` From 5bba36024116db6986848ea09aef0e1871a0a815 Mon Sep 17 00:00:00 2001 From: Vlad Balin Date: Tue, 27 Oct 2015 00:59:47 -0400 Subject: [PATCH 2/3] Update stores.md --- examples/stores.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stores.md b/examples/stores.md index 09efeaf..913e7a6 100644 --- a/examples/stores.md +++ b/examples/stores.md @@ -18,7 +18,7 @@ var Top = React.createClass({ }), attributes : { - role : Role.from( 'roles' ) // render on instance replace + role : Role.from( 'store.roles' ) // render on instance replace }, render(){ From 189612dd3e7b99d7c861cfd0001064f206922bc1 Mon Sep 17 00:00:00 2001 From: Vlad Balin Date: Thu, 5 Nov 2015 11:56:25 -0500 Subject: [PATCH 3/3] updated proposal --- examples/stores.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/stores.md b/examples/stores.md index 913e7a6..e89b7a8 100644 --- a/examples/stores.md +++ b/examples/stores.md @@ -10,11 +10,11 @@ ```javascript var Top = React.createClass({ // members fetched on first access, no updates on changes - useStore : LazyStore.defaults({ + Store : LazyStore.defaults({ users : User.Collection, roles : Role.Collection, channelSets : ChannelSet.Collection - _api : MasterStore.take( api ).merge() // create proxy native props accessors + _api : MasterStore.take( api ).has.proxy() // create proxy native props accessors }), attributes : { @@ -38,13 +38,24 @@ var Roles = React.createClass({ // render only if prop values change isolated : true, // same as mixins : [ PureRenderMixin ], + propTypes : { + collection : React.PropTypes.instanceof( Role.Collection ).isRequired, + selected : React.PropTypes.func + }, + + mixins : [ PureRenderMixin ], + listenToProps : 'collection', // listen to triggerWhenChanged if string + attributes : { - roles : Collection.take( 'props.collection' ), // -> this._owner.props.collection - selected : Role.from( 'roles' ).onChange( 'props.selected' ) // -> - /* install hook .set( function( value ){ - this._owner.props.selected( value ); + selected : Role.from( '^props.roles' ).has.watcher( '^props.selected' ) // -> + /* ^ resolved as (this.collection || this._owner).props.roles + install hook .set( function( value ){ + ref.call( this )( value ); return value; - }) */ + }) + + this.listenTo( this, 'change:selected', function( model, attr ){ handler( attr ) } ) + */ }, render(){