Skip to content

Instantly share code, notes, and snippets.

@wegorich
Created January 11, 2018 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wegorich/b18816f46637dc6e3cb71023da8ee149 to your computer and use it in GitHub Desktop.
Save wegorich/b18816f46637dc6e3cb71023da8ee149 to your computer and use it in GitHub Desktop.
test js decorator to work as class extension aka class mixins
import { bindActionCreators } from 'redux';
import { simpleActions } from 'redux-pirate-actions';
function syncInit() {
this.syncUnsubscribe();
this._sync();
this._unsubscribe = this.store.subscribe(this._sync.bind(this));
}
function syncUnsubscribe() {
this._unsubscribe && this._unsubscribe();
this._unsubscribe = null;
}
function _sync() {
let state = this.store.getState();
this.sync(state);
}
function showErrors(state) {
if (state.errors.length > 0) {
let err = state.errors[state.errors.length - 1];
let message = err.message ||
err.data && err.data.error || err;
if (message) {
// avoid showing same error multiple times
clearTimeout(this.errorTimeout);
this.errorTimeout = setTimeout(()=> {
if (!this.toast) {
console.warn(typeof this, ' should have *this.toast* object to show errors: ', message);
} else {
this.toast.error(message);
}
}, 50);
}
this.actions.clearErrors();
}
}
// the sync sould be overrided;
//
function sync(state) {
console.log('default sync')
}
// it also can be overrided
// please use super.bind in this situation
//
function bind() {
this.syncInit();
}
// this kind of optimization
// cause bind / unbind never trigger more then once for views
function attached() {
this.syncInit();
}
// this kind of optimization
function detached() {
this.syncUnsubscribe();
}
function unbind() {
this.syncUnsubscribe();
}
let actionsCallbacks = null;
let actionsWr = null;
function assign(obj, behavior) {
Object.keys(behavior).forEach(key => {
if (!obj.prototype[key]) {
obj.prototype[key] = behavior[key];
}
});
}
export let useStoreDecorator = (actions, store) => () => {
actionsWr = actionsWr || simpleActions(actions);
actionsCallbacks = actionsCallbacks || bindActionCreators(actionsWr, store.dispatch);
let storableViewBehavior = {
actions: actionsCallbacks,
store,
syncInit,
syncUnsubscribe,
_sync,
showErrors,
sync,
bind,
attached,
detached,
unbind
};
return function(target, key, descriptor) {
// handle when used as a parameter
if (typeof descriptor === 'number') {
assign(target, storableViewBehavior);
return;
}
// if it's true then we injecting rest into function and not Class constructor
if (descriptor) {
const fn = descriptor.value;
assign(fn, storableViewBehavior);
} else {
assign(target, storableViewBehavior);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment