UNPKG

@xailabs/altx

Version:

Flux flavor based on alt.js

95 lines (78 loc) 3.74 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = bindHandlers; var _decorators = require('alt-utils/lib/decorators'); var _flatten = require('../utils/flatten'); var _flatten2 = _interopRequireDefault(_flatten); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // TODO clean up and refactor terminoloy, potentially deprecate the old "handlers" system // (viewActions are now called handlers, e.g. handlerFactory) /** * Decorates a store with any number of action handlers. */ function bindHandlers(actions) { for (var _len = arguments.length, handlers = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { handlers[_key - 1] = arguments[_key]; } return function decorateStore(storeClass) { // attach bound handler methods to the store class for each handler definition (0, _flatten2.default)(handlers).forEach(function (handler) { return attachBoundHandler(storeClass, actions[handler.name], handler); }); return storeClass; }; } /** * Attaches a single reducer handling to the store. * * A new handler method will be created on the store class. * The handler method invokes the reducer giving it the current store state. * It then sets the reducer result as the new store state. * * If a sideEffect function is defined, it will be called with the signature `{state, prevState, payload}` * * @param {object} storeClass - The class of the store to be decorated * @param {object} action - An altjs action * @param {object} handler - An handler object with `{name[, reducer, sideEffect]}` */ function attachBoundHandler(storeClass, action, handler) { // name is required var methodName = '__handle_' + handler.name; if (storeClass.prototype[methodName]) throw new Error('Duplicate method "' + methodName + '"'); /** * Handles an action call and sets the next state of the store. * * @param {any} payload - the single argument that can be specified when calling an action. * If you need to use more than one argument, use an object with any properties you need. */ storeClass.prototype[methodName] = function handleAction(payload) { var reducer = handler.hasOwnProperty('reducer') && handler.reducer; var sideEffect = handler.hasOwnProperty('sideEffect') && handler.sideEffect; var currentState = this.state; // the actual operation: run the reducer and set its result as state var nextState = currentState; if (reducer) { try { nextState = reducer(currentState, payload); } catch (error) { console.error('Error in reducer (' + handler.name + ', ' + handler.name + ')', error); } } if (nextState) { this.setState(nextState); } else if (reducer) { console.warn('reducer "' + handler.name + '" in call "' + handler.name + '" did not return a new state.\n Either you forgot to return it, or if no state change is required, maybe you should use a sideEffect instead of a reducer.\n '); } if (sideEffect) { try { sideEffect({ state: nextState, prevState: currentState, payload: payload }); } catch (error) { console.error('Error in sideEffect (' + handler.name + ', ' + handler.name + ')', error); } } }; var bindhandler = (0, _decorators.bind)(action); bindhandler(storeClass, methodName, Object.getOwnPropertyDescriptor(storeClass.prototype, methodName)); };