UNPKG

preact-batteries

Version:

Batteries for you projects with Preact, TypeScript (or Babel)

129 lines (104 loc) 3.41 kB
import { CompatibleComponentInterface } from "../component-modules/module-system"; import { StoreInterface } from "../component-modules/auth-dependent-component"; interface Properties { [property: string]: any; } export class PropertyGetterUndefinedError extends Error { constructor(property: string) { super( `[StoreListener]: property ${property} does not have valid getter method or public availability in the store` ); } } interface PropertyGetterObject { property: string; customGetterName?: string; onAfterGetCallback?: Function; } export class StoreListener { private store: StoreInterface; private component: CompatibleComponentInterface<any, any>; private propertiesGetters: Array<PropertyGetterObject> = []; constructor(c: CompatibleComponentInterface<any, any>, s: StoreInterface) { this.store = s; this.component = c; } public add( property: string, customGetterName: string = undefined, onAfterGetCallback: Function = undefined ): StoreListener { this.getPropertyFromStore(property, customGetterName, true); this.propertiesGetters.push({ property, customGetterName, onAfterGetCallback }); return this; } public listen() { const c = this.component; const oldComponentWillMount = c.componentWillMount; const store = this.store; const propertiesGetters = this.propertiesGetters; const getPropertyFromStore = this.getPropertyFromStore.bind(this); const changeListener = function changeListener() { const newState = {}; propertiesGetters.forEach(p => { newState[p.property] = getPropertyFromStore(p.property, p.customGetterName); }); this.setState(newState); }.bind(c); c.componentWillMount = function() { store.addChangeListener(changeListener); oldComponentWillMount && oldComponentWillMount.call(this); }.bind(c); const oldComponentWillUnmount = c.componentWillUnmount; store.removeChangeListener(changeListener); c.componentWillUnmount = function() { store.removeChangeListener(changeListener); oldComponentWillUnmount && oldComponentWillUnmount.call(this); }.bind(c); } private getPropertyFromStore( property: string, customGetter: string = undefined, onlyCheckAvailability: boolean = false ) { if (customGetter) { if (typeof this.store[customGetter] === "undefined") { throw new PropertyGetterUndefinedError(property); } if (!onlyCheckAvailability) { return this.store[customGetter]; } } const getterMethod = "get" + property.charAt(0).toUpperCase() + property.slice(1); const stateProperty: boolean = (this.store.getState && typeof this.store.getState === "function" && typeof this.store.getState() === "object" && this.store.getState().hasOwnProperty(property)) ? true : false; if ( typeof this.store[property] === "undefined" && typeof this.store[getterMethod] === "undefined" && !stateProperty ) { throw new PropertyGetterUndefinedError(property); } if (!onlyCheckAvailability) { if (stateProperty) { const state = this.store.getState(); return state[property]; } return this.store[property] ? this.store[property] : this.store[getterMethod]; } } }