UNPKG

fastflux

Version:

Message driven reactive state management

115 lines (91 loc) 3.23 kB
'use strict'; exports.__esModule = true; exports.createSubscriber = createSubscriber; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _utilsIndexJs = require('../utils/index.js'); var _react = require('react'); var _observableStateJs = require('./observable/state.js'); var _observableStateJs2 = _interopRequireDefault(_observableStateJs); /** * Higher-order component that automatically subscribes to * {@link ObservableState} props. * * @example * let text = new ObservableState("Foo"); * * class Label extends React.Component { * render() { * return <div>{this.props.text}</div>; * } * } * Label = createSubscriber(Label); * * // Render <Label> with text "Foo" * React.render(<Label text={text} />, mountPoint); * * // After 1 second change text to "Bar" * setTimeout(() => text.emit("Bar"), 1000); * * @param {React.Component} component - the component to wrap * @returns {React.Component} */ function createSubscriber(component) { var wrapper = function wrapper(props, context) { _react.Component.call(this, props, context); this.normalProps = {}; this.observableProps = {}; this.updaters = {}; var state = {}; for (var k in this.props) { var prop = this.props[k]; if (!_utilsIndexJs.isObservableState(prop)) this.normalProps[k] = prop;else { this.observableProps[k] = prop; state[k] = prop.getState(); } } this.state = state; }; wrapper.prototype = Object.create(_react.Component.prototype, { constructor: { value: wrapper }, componentWillMount: { value: function value() { var _this = this; var _loop = function (k) { var observable = _this.observableProps[k]; var updater = _this.updaters[k] = function (state) { var updated = {}; updated[k] = state; _this.setState(updated); }; observable.subscribe(updater); }; for (var k in this.observableProps) { _loop(k); } } }, componentWillUnmount: { value: function value() { for (var k in this.updaters) { this.observableProps[k].unsubscribe(this.updaters[k]); delete this.updaters[k]; } } }, componentWillReceiveProps: { value: function value(nextProps) { for (var k in this.observableProps) { if (nextProps[k] !== this.observableProps[k]) throw new Error("Cannot change an observable state prop once initialized. " + "To change the value, call setState"); } for (var k in this.normalProps) { if (nextProps[k] === void 0) delete this.normalProps[k]; } for (var k in nextProps) { var prop = nextProps[k]; if (!(k in this.observableProps)) { if (!_utilsIndexJs.isObservableState(prop)) this.normalProps[k] = prop;else throw new Error("Cannot change non-observable prop to observable once initialized"); } } } }, render: { value: function value() { return _react.createElement(component, _utilsIndexJs.assign({}, this.normalProps, this.state)); } } }); return wrapper; } ;