Skip to content

Commit d8693f4

Browse files
committed
release v2.0.1
1 parent b693f41 commit d8693f4

File tree

5 files changed

+292
-4
lines changed

5 files changed

+292
-4
lines changed

dist/es6/autoBind.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.default = autoBind;
7+
// do not bind these, they should not be directly invoked or passed as callbacks by the user
8+
var reactInternals = new Set(['constructor', 'render', 'componentWillMount', 'componentDidMount', 'componentWillReceiveProps', 'shouldComponentUpdate', 'componentWillUpdate', 'componentDidUpdate', 'componentWillUnmount']);
9+
10+
// bind the methods from proto to the passed context object and assign them to the context
11+
function autoBind(context, proto, isReact) {
12+
var _iteratorNormalCompletion = true;
13+
var _didIteratorError = false;
14+
var _iteratorError = undefined;
15+
16+
try {
17+
for (var _iterator = Object.getOwnPropertyNames(proto)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
18+
var key = _step.value;
19+
20+
var value = proto[key];
21+
22+
if (typeof value === 'function' && !(isReact && reactInternals.has(key))) {
23+
context[key] = value.bind(context);
24+
}
25+
}
26+
} catch (err) {
27+
_didIteratorError = true;
28+
_iteratorError = err;
29+
} finally {
30+
try {
31+
if (!_iteratorNormalCompletion && _iterator.return) {
32+
_iterator.return();
33+
}
34+
} finally {
35+
if (_didIteratorError) {
36+
throw _iteratorError;
37+
}
38+
}
39+
}
40+
}

dist/es6/easyComp.js

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
8+
9+
var _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; }; }();
10+
11+
exports.default = easyComp;
12+
13+
var _react = require('react');
14+
15+
var _observerUtil = require('@nx-js/observer-util');
16+
17+
var _autoBind = require('./autoBind');
18+
19+
var _autoBind2 = _interopRequireDefault(_autoBind);
20+
21+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22+
23+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
24+
25+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
26+
27+
function _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; }
28+
29+
var REACTIVE_RENDER = Symbol('reactive render');
30+
31+
function easyComp(Comp) {
32+
if (typeof Comp !== 'function') {
33+
throw new TypeError('easyComp expects a component as argument.');
34+
}
35+
36+
// wrap stateless components in a class
37+
if (isStatelessComp(Comp)) {
38+
Comp = statelessToStatefulComp(Comp);
39+
} else if (hasComponentShouldUpdate(Comp)) {
40+
// shouldComponentUpdate is optimized by easyState, overwriting it would add zero or less value
41+
throw new Error('easyState optimizes shouldComponentUpdate, do not implement it.');
42+
}
43+
44+
return toReactiveComp(Comp);
45+
}
46+
47+
function isStatelessComp(Comp) {
48+
return !(Comp.prototype && Comp.prototype.render) && !_react.Component.isPrototypeOf(Comp);
49+
}
50+
51+
function statelessToStatefulComp(StatelessComp) {
52+
var _class, _temp;
53+
54+
return _temp = _class = function (_Component) {
55+
_inherits(StatefulComp, _Component);
56+
57+
function StatefulComp() {
58+
_classCallCheck(this, StatefulComp);
59+
60+
return _possibleConstructorReturn(this, (StatefulComp.__proto__ || Object.getPrototypeOf(StatefulComp)).apply(this, arguments));
61+
}
62+
63+
_createClass(StatefulComp, [{
64+
key: 'render',
65+
66+
67+
// call the original function component inside the render method
68+
69+
// proxy react specific static variables to the stateful component
70+
// from the stateless component
71+
value: function render() {
72+
return StatelessComp.call(this, this.props, this.context);
73+
}
74+
}]);
75+
76+
return StatefulComp;
77+
}(_react.Component), _class.displayName = StatelessComp.displayName || StatelessComp.name, _class.contextTypes = StatelessComp.contextTypes, _class.propTypes = StatelessComp.propTypes, _class.defaultProps = StatelessComp.defaultProps, _temp;
78+
}
79+
80+
function hasComponentShouldUpdate(Comp) {
81+
return typeof Comp.prototype.shouldComponentUpdate === 'function';
82+
}
83+
84+
function toReactiveComp(Comp) {
85+
var _class2, _temp2;
86+
87+
// return a HOC which overwrites render, shouldComponentUpdate and componentWillUnmount
88+
// it decides when to run the new reactive methods and when to proxy to the original methods
89+
return _temp2 = _class2 = function (_Comp) {
90+
_inherits(EasyHOC, _Comp);
91+
92+
// proxy react specific static variables to the HOC from the component
93+
function EasyHOC(props) {
94+
_classCallCheck(this, EasyHOC);
95+
96+
// auto bind non react specific original methods to the component instance
97+
var _this2 = _possibleConstructorReturn(this, (EasyHOC.__proto__ || Object.getPrototypeOf(EasyHOC)).call(this, props));
98+
99+
(0, _autoBind2.default)(_this2, Comp.prototype, true);
100+
101+
// turn the state into an observable object, which triggers rendering on mutations
102+
_this2.state = (0, _observerUtil.observable)(_this2.state);
103+
return _this2;
104+
}
105+
106+
_createClass(EasyHOC, [{
107+
key: 'render',
108+
value: function render() {
109+
var _this3 = this;
110+
111+
// if it is the first direct render from react call there is no reactive render yet
112+
if (!this[REACTIVE_RENDER]) {
113+
var result = void 0;
114+
// create a reactive render, which is automatically called by easyState on relevant state and store mutations
115+
// the passed function is executed right away synchronously once by easyState
116+
this[REACTIVE_RENDER] = (0, _observerUtil.observe)(function () {
117+
// if it is the first (synchronous) execution, call the original component's render
118+
// this is necessary because forceUpdate can not be called synchronously inside render functions
119+
if (!_this3[REACTIVE_RENDER]) {
120+
result = _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'render', _this3).call(_this3);
121+
} else {
122+
// if it is a later reactive, asynchronous execution - triggered by easyState - forceUpdate the original component
123+
// this is necessary, because calling render would require the result to be returned
124+
// which is not possible from this asynchronous context
125+
_get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'forceUpdate', _this3).call(_this3);
126+
}
127+
});
128+
// return the result from super.render() inside the reactive render on the first render execution
129+
return result;
130+
} else {
131+
// return the original component's render result on direct calls from react
132+
return _get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'render', this).call(this);
133+
}
134+
}
135+
136+
// react should trigger updates on prop changes, while easyState handles state changes
137+
138+
}, {
139+
key: 'shouldComponentUpdate',
140+
value: function shouldComponentUpdate(nextProps) {
141+
var props = this.props;
142+
143+
var keys = Object.keys(props);
144+
var nextKeys = Object.keys(nextProps);
145+
146+
// component should update if the number of its props changed
147+
if (keys.length !== nextKeys.length) {
148+
return true;
149+
}
150+
151+
// component should update if any of its props changed value
152+
var _iteratorNormalCompletion = true;
153+
var _didIteratorError = false;
154+
var _iteratorError = undefined;
155+
156+
try {
157+
for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
158+
var key = _step.value;
159+
160+
if (props[key] !== nextProps[key]) {
161+
return true;
162+
}
163+
}
164+
165+
// do not let react update the comp otherwise, leave state triggered updates to easyState
166+
} catch (err) {
167+
_didIteratorError = true;
168+
_iteratorError = err;
169+
} finally {
170+
try {
171+
if (!_iteratorNormalCompletion && _iterator.return) {
172+
_iterator.return();
173+
}
174+
} finally {
175+
if (_didIteratorError) {
176+
throw _iteratorError;
177+
}
178+
}
179+
}
180+
181+
return false;
182+
}
183+
}, {
184+
key: 'componentWillUnmount',
185+
value: function componentWillUnmount() {
186+
// clean up memory used by easyState
187+
(0, _observerUtil.unobserve)(this[REACTIVE_RENDER]);
188+
189+
// also call user defined componentWillUnmount to allow the user
190+
// to clean up additional memory
191+
if (_get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'componentWillUnmount', this)) {
192+
_get(EasyHOC.prototype.__proto__ || Object.getPrototypeOf(EasyHOC.prototype), 'componentWillUnmount', this).call(this);
193+
}
194+
}
195+
}]);
196+
197+
return EasyHOC;
198+
}(Comp), _class2.displayName = Comp.displayName || Comp.name, _class2.contextTypes = Comp.contextTypes, _class2.propTypes = Comp.propTypes, _class2.defaultProps = Comp.defaultProps, _temp2;
199+
}

dist/es6/easyStore.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
8+
9+
exports.default = easyStore;
10+
11+
var _observerUtil = require('@nx-js/observer-util');
12+
13+
var _autoBind = require('./autoBind');
14+
15+
var _autoBind2 = _interopRequireDefault(_autoBind);
16+
17+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18+
19+
function easyStore(store) {
20+
if ((typeof store === 'undefined' ? 'undefined' : _typeof(store)) !== 'object' || store === null) {
21+
throw new TypeError('easyStore expects an object as argument');
22+
}
23+
24+
// create an observable object from the passed store
25+
// and bind all of its methods to the created observable
26+
var observableStore = (0, _observerUtil.observable)(store);
27+
(0, _autoBind2.default)(observableStore, store, false);
28+
return observableStore;
29+
}

dist/es6/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.easyStore = exports.easyComp = undefined;
7+
8+
var _easyComp = require('./easyComp');
9+
10+
var _easyComp2 = _interopRequireDefault(_easyComp);
11+
12+
var _easyStore = require('./easyStore');
13+
14+
var _easyStore2 = _interopRequireDefault(_easyStore);
15+
16+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17+
18+
exports.easyComp = _easyComp2.default;
19+
exports.easyStore = _easyStore2.default;

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"name": "react-easy-state",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "React Easy State provides a healthy balance of local and global state management in a simple, scalable way",
5-
"main": "dist/easyState.js",
6-
"module": "src/index.js",
5+
"main": "dist/es5.js",
6+
"module": "dist/es6/index.js",
77
"scripts": {
88
"test": "jest --coverage",
99
"test:watch": "jest --watch",
@@ -12,7 +12,7 @@
1212
"coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls",
1313
"lint": "standard",
1414
"lint:fix": "standard --fix",
15-
"build": "webpack",
15+
"build": "babel ./src --out-dir dist/es6 && webpack",
1616
"build-examples": "webpack --config ./webpack.examples.js",
1717
"build-examples-dev": "webpack --config ./webpack.examples.js --watch",
1818
"build-all": "npm run build && npm run build-examples"
@@ -56,6 +56,7 @@
5656
"@nx-js/observer-util": "3"
5757
},
5858
"devDependencies": {
59+
"babel-cli": "^6.24.1",
5960
"babel-core": "6.25.0",
6061
"babel-eslint": "^7.2.3",
6162
"babel-jest": "^20.0.3",

0 commit comments

Comments
 (0)