-
Notifications
You must be signed in to change notification settings - Fork 320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
class extends Store #344
class extends Store #344
Changes from all commits
f4bb812
89fe4d1
249b4e0
08b1172
1c24270
0c58468
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import Alt, { Store } from './' | ||
|
||
const alt = new Alt() | ||
|
||
const actions = alt.generateActions('foo') | ||
|
||
//class MyStore extends Store { | ||
// constructor(one, two, three) { | ||
// super() | ||
// | ||
// this.state = { x: 1 } | ||
// | ||
// this.bindAction(actions.foo, () => { | ||
// this.setState({ x: this.state.x + 1 }) | ||
// }) | ||
// } | ||
//} | ||
//const store = alt.register(1, 2, 3)(MyStore) | ||
|
||
class MyStore { | ||
constructor() { | ||
this.state = { x: 1 } | ||
this.bindActions(actions) | ||
this.exportPublicMethods({ | ||
bar: this.bar.bind(this) | ||
}) | ||
} | ||
|
||
foo() { | ||
this.setState({ x: this.state.x + 1 }) | ||
} | ||
|
||
bar() { | ||
return this.state.x | ||
} | ||
} | ||
|
||
const store = alt.createStore(MyStore) | ||
|
||
console.log(store.bar()) | ||
|
||
store.listen(state => console.log('CHANGED', state)) | ||
|
||
actions.foo() | ||
actions.foo() | ||
actions.foo() | ||
actions.foo() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,13 @@ import { Dispatcher } from 'flux' | |
|
||
import * as StateFunctions from './utils/StateFunctions' | ||
import * as fn from '../utils/functions' | ||
import * as store from './store' | ||
import * as utils from './utils/AltUtils' | ||
import makeAction from './actions' | ||
|
||
import registerStore from './store/register' | ||
|
||
import Store from './store' | ||
|
||
class Alt { | ||
constructor(config = {}) { | ||
this.config = config | ||
|
@@ -27,44 +30,6 @@ class Alt { | |
this.batchingFunction(() => this.dispatcher.dispatch({ action, data, details })) | ||
} | ||
|
||
createUnsavedStore(StoreModel, ...args) { | ||
const key = StoreModel.displayName || '' | ||
store.createStoreConfig(this.config, StoreModel) | ||
const Store = store.transformStore(this.storeTransforms, StoreModel) | ||
|
||
return fn.isFunction(Store) | ||
? store.createStoreFromClass(this, Store, key, ...args) | ||
: store.createStoreFromObject(this, Store, key) | ||
} | ||
|
||
createStore(StoreModel, iden, ...args) { | ||
let key = iden || StoreModel.displayName || StoreModel.name || '' | ||
store.createStoreConfig(this.config, StoreModel) | ||
const Store = store.transformStore(this.storeTransforms, StoreModel) | ||
|
||
if (this.stores[key] || !key) { | ||
if (this.stores[key]) { | ||
utils.warn( | ||
`A store named ${key} already exists, double check your store ` + | ||
`names or pass in your own custom identifier for each store` | ||
) | ||
} else { | ||
utils.warn('Store name was not specified') | ||
} | ||
|
||
key = utils.uid(this.stores, key) | ||
} | ||
|
||
const storeInstance = fn.isFunction(Store) | ||
? store.createStoreFromClass(this, Store, key, ...args) | ||
: store.createStoreFromObject(this, Store, key) | ||
|
||
this.stores[key] = storeInstance | ||
StateFunctions.saveInitialSnapshot(this, key) | ||
|
||
return storeInstance | ||
} | ||
|
||
generateActions(...actionNames) { | ||
const actions = { name: 'global' } | ||
return this.createActions(actionNames.reduce((obj, action) => { | ||
|
@@ -77,6 +42,51 @@ class Alt { | |
return makeAction(this, 'global', name, implementation, obj) | ||
} | ||
|
||
createUnsavedStore(StoreModel, ...args) { | ||
StoreModel.config = fn.assign({ | ||
invisible: true | ||
}, StoreModel.config) | ||
return this.createStore(StoreModel, null, ...args) | ||
} | ||
|
||
createStore(StoreModel, iden, ...args) { | ||
// pull all prototype methods out | ||
const proto = utils.getInternalMethods(StoreModel, true) | ||
|
||
// force inheritance on store | ||
utils.inherit(StoreModel, Store, Object.keys(proto).reduce((obj, name) => { | ||
obj[name] = { | ||
value: StoreModel.prototype[name], | ||
enumerable: false, | ||
writable: true, | ||
configurable: true | ||
} | ||
return obj | ||
}, {})) | ||
|
||
// setup the a container store which will call Store first | ||
// then your store | ||
function FauxStore() { | ||
Store.prototype.constructor.apply(this, arguments) | ||
StoreModel.prototype.constructor.apply(this, arguments) | ||
} | ||
utils.inherit(FauxStore, StoreModel) | ||
|
||
if (iden) FauxStore.displayName = iden | ||
return this.register(...args)(FauxStore) | ||
} | ||
|
||
register(...args) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the intended syntax something like @alt.register(arg1, arg2)
class MyStore extends Store { ... } With the latter above I think you just naturally get @alt.register
class MyStore extends Store { ... } which ought to be good enough for any sane use case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 reasonable. |
||
return (Class) => { | ||
const instance = new Class(...args) | ||
if (instance instanceof Store) { | ||
return registerStore(this, instance, Class) | ||
} else { | ||
throw new Error('wtf') | ||
} | ||
} | ||
} | ||
|
||
createActions(ActionsClass, exportObj = {}, ...argsForConstructor) { | ||
const actions = {} | ||
const key = utils.uid( | ||
|
@@ -212,6 +222,8 @@ class Alt { | |
} | ||
return alt | ||
} | ||
|
||
static Store = Store | ||
} | ||
|
||
export default Alt |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work if
StoreModel
extends another class? Looks likegetInternalMethods
might have to walk up the prototype chain forStoreModel
for this to work.I think it'd be easier just to pull out the
constructor
functionality on the baseStore
class into an#init()
method, then invoke that (in bothStore#constructor
and for this), without messing withStoreModel
's prototype.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah it doesn't it should walk up the proto chain.
I doubt this will work with proper ES6 classes anyway, I may just nuke this. This was just a fun experiment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW my thought with using the base
Store
effectively as a mixin is that you fully control that, so you know that it doesn't have any superclasses (or if it does, you know how they're set up), whereas you can't assume anything about whatever crazy thing the user passes in tocreateStore
.