@@ -14523,8 +14523,10 @@ Object.defineProperty(exports, "__esModule", {
1452314523 value: true
1452414524});
1452514525exports.default = autoBind;
14526+ // do not bind these, they should not be directly invoked or passed as callbacks by the user
1452614527var reactInternals = new Set(['constructor', 'render', 'componentWillMount', 'componentDidMount', 'componentWillReceiveProps', 'shouldComponentUpdate', 'componentWillUpdate', 'componentDidUpdate', 'componentWillUnmount']);
1452714528
14529+ // bind the methods from proto to the passed context object and assign them to the context
1452814530function autoBind(context, proto, isReact) {
1452914531 var _iteratorNormalCompletion = true;
1453014532 var _didIteratorError = false;
@@ -27058,7 +27060,7 @@ var _get = function get(object, property, receiver) { if (object === null) objec
2705827060
2705927061var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
2706027062
27061- exports.default = easyCompHOC ;
27063+ exports.default = easyComp ;
2706227064
2706327065var _react = __webpack_require__(25);
2706427066
@@ -27076,91 +27078,129 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
2707627078
2707727079function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
2707827080
27079- var OBSERVED_RENDER = Symbol('observed render');
27080- var IS_DIRECT_RENDER = Symbol('is direct render');
27081- var RENDER_RESULT = Symbol('render result');
27081+ var REACTIVE_RENDER = Symbol('reactive render');
2708227082
27083- function easyCompHOC(WrappedComp ) {
27084- if (typeof WrappedComp !== 'function') {
27085- throw new TypeError('easyComp expects a component class or function as argument.');
27083+ function easyComp(Comp ) {
27084+ if (typeof Comp !== 'function') {
27085+ throw new TypeError('easyComp expects a component as argument.');
2708627086 }
2708727087
27088- if ((!WrappedComp.prototype || !WrappedComp.prototype.render) && !WrappedComp.isReactClass && !_react.Component.isPrototypeOf(WrappedComp)) {
27089- var renderer = WrappedComp;
27090- WrappedComp = function (_Component) {
27091- _inherits(WrappedComp, _Component);
27088+ // wrap stateless components in a class
27089+ if (isStatelessComp(Comp)) {
27090+ Comp = statelessToStatefulComp(Comp);
27091+ } else if (hasComponentShouldUpdate(Comp)) {
27092+ // shouldComponentUpdate is optimized by easyState, overwriting it would add zero or less value
27093+ throw new Error('easyState optimizes shouldComponentUpdate, do not implement it.');
27094+ }
27095+
27096+ return toReactiveComp(Comp);
27097+ }
27098+
27099+ function isStatelessComp(Comp) {
27100+ return !(Comp.prototype && Comp.prototype.render) && !_react.Component.isPrototypeOf(Comp);
27101+ }
27102+
27103+ function statelessToStatefulComp(StatelessComp) {
27104+ var _class, _temp;
27105+
27106+ return _temp = _class = function (_Component) {
27107+ _inherits(StatefulComp, _Component);
27108+
27109+ function StatefulComp() {
27110+ _classCallCheck(this, StatefulComp);
27111+
27112+ return _possibleConstructorReturn(this, (StatefulComp.__proto__ || Object.getPrototypeOf(StatefulComp)).apply(this, arguments));
27113+ }
27114+
27115+ _createClass(StatefulComp, [{
27116+ key: 'render',
27117+
2709227118
27093- function WrappedComp() {
27094- _classCallCheck(this, WrappedComp);
27119+ // call the original function component inside the render method
2709527120
27096- return _possibleConstructorReturn(this, (WrappedComp.__proto__ || Object.getPrototypeOf(WrappedComp)).apply(this, arguments));
27121+ // proxy react specific static variables to the stateful component
27122+ // from the stateless component
27123+ value: function render() {
27124+ return StatelessComp.call(this, this.props, this.context);
2709727125 }
27126+ }]);
2709827127
27099- _createClass(WrappedComp, [{
27100- key: 'render',
27101- value: function render() {
27102- return renderer.call(this, this.props, this.context);
27103- }
27104- }]);
27128+ return StatefulComp;
27129+ }(_react.Component), _class.displayName = StatelessComp.displayName || StatelessComp.name, _class.contextTypes = StatelessComp.contextTypes, _class.propTypes = StatelessComp.propTypes, _class.defaultProps = StatelessComp.defaultProps, _temp;
27130+ }
2710527131
27106- return WrappedComp;
27107- }(_react.Component);
27108- WrappedComp.displayName = renderer.displayName || renderer.name;
27109- WrappedComp.contextTypes = renderer.contextTypes;
27110- WrappedComp.propTypes = renderer.propTypes;
27111- WrappedComp.defaultProps = renderer.defaultProps;
27112- }
27132+ function hasComponentShouldUpdate(Comp) {
27133+ return typeof Comp.prototype.shouldComponentUpdate === 'function';
27134+ }
2711327135
27114- if (typeof WrappedComp.prototype.shouldComponentUpdate === 'function') {
27115- throw new Error('Do not implement shouldComponentUpdate, easyState already optimizes it for you!');
27116- }
27136+ function toReactiveComp(Comp) {
27137+ var _class2, _temp2;
2711727138
27118- return function (_WrappedComp) {
27119- _inherits(EasyCompWrapper, _WrappedComp);
27139+ // return a HOC which overwrites render, shouldComponentUpdate and componentWillUnmount
27140+ // it decides when to run the new reactive methods and when to proxy to the original methods
27141+ return _temp2 = _class2 = function (_Comp) {
27142+ _inherits(EasyHOC, _Comp);
2712027143
27121- function EasyCompWrapper(props) {
27122- _classCallCheck(this, EasyCompWrapper);
27144+ // proxy react specific static variables to the HOC from the component
27145+ function EasyHOC(props) {
27146+ _classCallCheck(this, EasyHOC);
2712327147
27124- var _this2 = _possibleConstructorReturn(this, (EasyCompWrapper.__proto__ || Object.getPrototypeOf(EasyCompWrapper)).call(this, props));
27148+ // auto bind non react specific original methods to the component instance
27149+ var _this2 = _possibleConstructorReturn(this, (EasyHOC.__proto__ || Object.getPrototypeOf(EasyHOC)).call(this, props));
2712527150
27126- (0, _autoBind2.default)(_this2, WrappedComp.prototype, true);
27151+ (0, _autoBind2.default)(_this2, Comp.prototype, true);
27152+
27153+ // turn the state into an observable object, which triggers rendering on mutations
2712727154 _this2.state = (0, _observerUtil.observable)(_this2.state);
2712827155 return _this2;
2712927156 }
2713027157
27131- _createClass(EasyCompWrapper , [{
27158+ _createClass(EasyHOC , [{
2713227159 key: 'render',
2713327160 value: function render() {
2713427161 var _this3 = this;
2713527162
27136- if (!this[OBSERVED_RENDER]) {
27137- this[OBSERVED_RENDER] = function () {
27138- if (_this3[IS_DIRECT_RENDER]) {
27139- _this3[RENDER_RESULT] = _get(EasyCompWrapper.prototype.__proto__ || Object.getPrototypeOf(EasyCompWrapper.prototype), 'render', _this3).call(_this3);
27163+ // if it is the first direct render from react call there is no reactive render yet
27164+ if (!this[REACTIVE_RENDER]) {
27165+ var result = void 0;
27166+ // create a reactive render, which is automatically called by easyState on relevant state and store mutations
27167+ // the passed function is executed right away synchronously once by easyState
27168+ this[REACTIVE_RENDER] = (0, _observerUtil.observe)(function () {
27169+ // if it is the first (synchronous) execution, call the original component's render
27170+ // this is necessary because forceUpdate can not be called synchronously inside render functions
27171+ if (!_this3[REACTIVE_RENDER]) {
27172+ result = _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'render', _this3).call(_this3);
2714027173 } else {
27141- _get(EasyCompWrapper.prototype.__proto__ || Object.getPrototypeOf(EasyCompWrapper.prototype), 'forceUpdate', _this3).call(_this3);
27174+ // if it is a later reactive, asynchronous execution - triggered by easyState - forceUpdate the original component
27175+ // this is necessary, because calling render would require the result to be returned
27176+ // which is not possible from this asynchronous context
27177+ _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'forceUpdate', _this3).call(_this3);
2714227178 }
27143- };
27179+ });
27180+ // return the result from super.render() inside the reactive render on the first render execution
27181+ return result;
27182+ } else {
27183+ // return the original component's render result on direct calls from react
27184+ return _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'render', this).call(this);
2714427185 }
27186+ }
2714527187
27146- this[IS_DIRECT_RENDER] = true;
27147- this[OBSERVED_RENDER] = (0, _observerUtil.observe)(this[OBSERVED_RENDER]);
27148- this[IS_DIRECT_RENDER] = false;
27188+ // react should trigger updates on prop changes, while easyState handles state changes
2714927189
27150- return this[RENDER_RESULT];
27151- }
2715227190 }, {
2715327191 key: 'shouldComponentUpdate',
27154- value: function shouldComponentUpdate(nextProps, nextState ) {
27192+ value: function shouldComponentUpdate(nextProps) {
2715527193 var props = this.props;
2715627194
2715727195 var keys = Object.keys(props);
2715827196 var nextKeys = Object.keys(nextProps);
2715927197
27198+ // component should update if the number of its props changed
2716027199 if (keys.length !== nextKeys.length) {
2716127200 return true;
2716227201 }
2716327202
27203+ // component should update if any of its props changed value
2716427204 var _iteratorNormalCompletion = true;
2716527205 var _didIteratorError = false;
2716627206 var _iteratorError = undefined;
@@ -27173,6 +27213,8 @@ function easyCompHOC(WrappedComp) {
2717327213 return true;
2717427214 }
2717527215 }
27216+
27217+ // do not let react update the comp otherwise, leave state triggered updates to easyState
2717627218 } catch (err) {
2717727219 _didIteratorError = true;
2717827220 _iteratorError = err;
@@ -27193,15 +27235,19 @@ function easyCompHOC(WrappedComp) {
2719327235 }, {
2719427236 key: 'componentWillUnmount',
2719527237 value: function componentWillUnmount() {
27196- if (_get(EasyCompWrapper.prototype.__proto__ || Object.getPrototypeOf(EasyCompWrapper.prototype), 'componentWillUnmount', this)) {
27197- return _get(EasyCompWrapper.prototype.__proto__ || Object.getPrototypeOf(EasyCompWrapper.prototype), 'componentWillUnmount', this).call(this);
27238+ // clean up memory used by easyState
27239+ (0, _observerUtil.unobserve)(this[REACTIVE_RENDER]);
27240+
27241+ // also call user defined componentWillUnmount to allow the user
27242+ // to clean up additional memory
27243+ if (_get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'componentWillUnmount', this)) {
27244+ _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'componentWillUnmount', this).call(this);
2719827245 }
27199- (0, _observerUtil.unobserve)(this[OBSERVED_RENDER]);
2720027246 }
2720127247 }]);
2720227248
27203- return EasyCompWrapper ;
27204- }(WrappedComp) ;
27249+ return EasyHOC ;
27250+ }(Comp), _class2.displayName = Comp.displayName || Comp.name, _class2.contextTypes = Comp.contextTypes, _class2.propTypes = Comp.propTypes, _class2.defaultProps = Comp.defaultProps, _temp2 ;
2720527251}
2720627252
2720727253/***/ }),
@@ -27407,9 +27453,11 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
2740727453
2740827454function easyStore(store) {
2740927455 if ((typeof store === 'undefined' ? 'undefined' : _typeof(store)) !== 'object' || store === null) {
27410- throw new TypeError('easyStore expects an object as argument. ');
27456+ throw new TypeError('easyStore expects an object as argument');
2741127457 }
2741227458
27459+ // create an observable object from the passed store
27460+ // and bind all of its methods to the created observable
2741327461 var observableStore = (0, _observerUtil.observable)(store);
2741427462 (0, _autoBind2.default)(observableStore, store, false);
2741527463 return observableStore;
0 commit comments