Skip to content

Instantly share code, notes, and snippets.

@uniphil
Created July 16, 2015 22:43
Show Gist options
  • Save uniphil/d8bf9b2691cab4c8551f to your computer and use it in GitHub Desktop.
Save uniphil/d8bf9b2691cab4c8551f to your computer and use it in GitHub Desktop.
reflux conventions
/**
* An example store to document sane conventions.
*
* Stores should implement these five methods at minimum.
* Additional methods (eg., event handlers) may be added.
* Never write directly to `this.data`, except in `init`
* and `setData`.
*
* A few methods are allowed to be called by external
* code, but it is strongly preferred that only the
* eventEmitter API is used (`exampleStore.listen`, etc.)
*/
var exampleStore = Reflux.createStore({
/**
* Initialize the store
*
* May be called by:
* * external code: no.
* * store method code: no.
* (it is automatically called by reflux)
*
* This method must initialize `this.data`.
* The store may set up listeners to actions and other
* here.
*/
init: function() {
this.data = []; // change `[]` as appropriate
// set up listeners
},
/**
* Update the value of the store
*
* May be called by:
* * external code: no.
* * local code: yes.
*
* A DG convention method, used to update the store's
* `setData` must be exclusively used to update `data`
* (except in `init`, the only other place it is allowed
* to write directly to `data`)
* This method should probably never do processing on
* `newData`; this implementation should be sufficient.
*/
setData: function(newData) {
this.data = newData;
this.emit();
},
/**
* Retrieve a clean, consumer-ready representation of
* the store's value
*
* May be called by:
* * external code: yes (but prefer `listen`).
* * local code: yes.
*
* Processing is allowed but not preferred.
* External users are allowed to call `get` directly,
* but are strongly recommended to listen to the store
* for changes and initial state instead.
*/
get: function() {
return this.data;
},
/**
* Notify listeners of updated store value
*
* May be called by:
* * external code: no.
* * local code: yes (but rarely needed).
*
* It is not usually necessary to call `emit`, since
* calling `setData` will cause `emit` to be called
* automatically. However, it is allowed.
* Emit should not change the value of `this.get()`.
* This implementation should be sufficient.
*/
emit: function() {
this.trigger(this.get());
},
/**
* Retrieve the current state of the store.
*
* May be called by:
* * external code: yes.
* * local code: no.
* (this method is part of the eventEmitter API)
*
* This implementation should be sufficient.
*/
getInitialState: function() {
return this.get();
},
});
/**
* An example for a record-like store holding a
* single updateable value, using the above
* conventions
*/
var configStore = react.createStore({
init: function() {
this.data = {
theme: 'blue',
layout: 'compact',
};
this.listenTo(configActions.setTheme, this.onSetTheme);
this.listenTo(configActions.setLayout, this.onSetLayout);
},
onSetTheme: function(theme) {
if (['blue', 'orange', 'gray'].indexOf(theme) === -1) {
throw new Error('Unknwon theme', theme);
}
this.update('theme', theme);
},
onSetLayout: function(layout) {
if (['compact', 'comfortable'].indexOf(layout) === -1) {
throw new Error('Unknown layout', layout);
}
this.update('layout', layout);
},
/**
* `update` is an extra convenience method to update
* part of the config. It wraps setData, which is now
* not used anywhere else.
*/
update: function(what, val) {
if (['theme', 'layout'].indexOf(what) === -1) {
throw new Error('Unknown config', what);
}
var newConfig = Object.assign({}, this.data);
newConfig[what] = val;
this.setData(newConfig);
},
setData: function(obj) {
this.data = obj;
this.emit();
},
get: function() {
return this.data;
},
emit: function() {
this.trigger(this.get());
},
getInitialState: function() {
return this.get();
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment