dataflux 1.15.1 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -254,6 +254,70 @@ function MyComponent() {
254
254
  }
255
255
  ```
256
256
 
257
+ ### Example 7 - React props and observability
258
+
259
+ If you pass an object as a prop to a React component, the component will not refresh if the object changes.
260
+
261
+ ```jsx
262
+ class MyComponent extends React.Component {
263
+ constructor(props) {
264
+ super(props);
265
+ }
266
+
267
+ componentDidMount() {
268
+ store.findAll("book", "books", this, ({price}) => price < 20);
269
+ }
270
+
271
+ render(){
272
+ const {books} = this.state;
273
+
274
+ return books.map(book =>
275
+ <BookView
276
+ // key={book.getFingerprint()}
277
+ book={book}
278
+ />);
279
+ }
280
+ }
281
+
282
+ class BookView extends React.Component {
283
+ constructor(props) {
284
+ super(props);
285
+ }
286
+
287
+ render(){
288
+ const {book} = this.props;
289
+
290
+ return <div>book.price</div>;
291
+ }
292
+ }
293
+
294
+
295
+
296
+ ```
297
+ If you now do `books[0].set("price", 18)`, the BookView object will not update the price. You could address this by adding a `key={book.getFingerprint()}` prop. However, this approach forces the mounting of the component at every object change.
298
+
299
+ A better approach is to use the method `didUpdate()` inside `componentDidUpdate` to check if any of the objects in the props changed.
300
+
301
+ ```jsx
302
+ class BookView extends React.Component {
303
+ constructor(props) {
304
+ super(props);
305
+ }
306
+
307
+ componentDidUpdate() {
308
+ store.didUpdate(this);
309
+ }
310
+
311
+ render(){
312
+ const {book} = this.props;
313
+
314
+ return <div>book.price</div>;
315
+ }
316
+ }
317
+ ```
318
+
319
+ Without further changes to the code, the new `book.price` will be rendered when the book object in the props is edited.
320
+
257
321
 
258
322
  ## Configuration
259
323
 
@@ -576,6 +640,7 @@ The store has the following method.
576
640
  | reset(type) | This method syncs all the objects in the store with the remote version offered by the REST APIs (`remote -> local`). Remote changes are applied locally, including adding/removing objects. Objects edited locally but not yet persisted are reverted to the corresponding remote object. If a model type is passed, only objects of that type will be reset. |
577
641
  | findSync(type, filterFunction) | This method returns the objects in a synchronous way (no Promise). However, *it works only if you already performed an async operation (e.g., like refresh, load, find, subscribe) or if you set lazyLoad to false and the store had enough time to load.* |
578
642
  | hasChanged(type, object) | This method receives in input a model type and an object (optional). It returns a boolean, `true` if the object is dirty (it changed but it has not yet being persisted). If the object is not passed, the method checks if any of the objects of the specified model type has changed. |
643
+ | didUpdate(context) | If you pass an object as a prop to a React component, the component will not refresh if the object changes. To address this, you can use this method inside the `componentDidUpdate` to check if any of the objects changed. See [example 6](#example-7---react-props-and-observability) |
579
644
 
580
645
  ### Insert vs. Mock
581
646
 
@@ -631,6 +696,7 @@ Each object created is enriched with the following methods.
631
696
  | getError() | If an operation on an object triggers an error, this error can be retrieved with `getError()`. This allows to observe specific objects' errors, instead of the generic `store.on("error", ...)`. |
632
697
  | getError(attributeName) | This method allows you to check if the specificed attribute generated any error according to the validation property specified in the model. See [objects validation](#objects-validation). |
633
698
  | setError(error) | Additionally to DataFlux's errors, you can trigger your own errors with this method. Other components observing this objet's error will be notified. |
699
+ | isDataflux() | This method returns true for all dataflux objects. |
634
700
 
635
701
  ### Deep Objects
636
702
  When a model is declared with the option `deep: true` (default, see [model creation](#models-creation)), all the sub objects will also offer many of the methods above.
@@ -718,7 +784,7 @@ class MyComponent extends React.Component {
718
784
  return <TextField
719
785
  value={book.title}
720
786
  onChange={store.handleChange(book, "title")}
721
- error={object.getError("title")}
787
+ error={object.getError("title")}
722
788
  // E.g., in material UI the test field will be red in case of errors
723
789
  />;
724
790
  }
package/dist/BasicObj.js CHANGED
@@ -78,6 +78,9 @@ var BasicObj = exports.BasicObj = /*#__PURE__*/function () {
78
78
  _classPrivateFieldInitSpec(this, _id, null);
79
79
  _classPrivateFieldInitSpec(this, _error, {});
80
80
  _classPrivateFieldInitSpec(this, _model, void 0);
81
+ _defineProperty(this, "isDataflux", function () {
82
+ return true;
83
+ });
81
84
  _defineProperty(this, "setId", function (id) {
82
85
  _this.id = id;
83
86
  });
@@ -22,12 +22,12 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
22
22
  function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
23
23
  function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
24
24
  function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
25
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
26
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
27
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
28
25
  function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
29
26
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
30
27
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
28
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
29
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
30
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
31
31
  function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
32
32
  function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } /*
33
33
  * MIT License
@@ -60,6 +60,19 @@ var ReactStore = exports["default"] = /*#__PURE__*/function (_ObserverStore) {
60
60
  _classCallCheck(this, ReactStore);
61
61
  _this = _callSuper(this, ReactStore, [options]);
62
62
  _classPrivateMethodInitSpec(_this, _ReactStore_brand);
63
+ _defineProperty(_this, "didUpdate", function (context) {
64
+ var _context$props;
65
+ var objects = Object.values((_context$props = context === null || context === void 0 ? void 0 : context.props) !== null && _context$props !== void 0 ? _context$props : {}).filter(function (i) {
66
+ return i.isDataflux();
67
+ });
68
+ var _f = objects.map(function (i) {
69
+ return i.getFingerprint();
70
+ }).join(".");
71
+ if (_f !== context.___obs_f) {
72
+ context.forceUpdate();
73
+ }
74
+ context.___obs_f = _f;
75
+ });
63
76
  _classPrivateFieldInitSpec(_this, _addSubscriptionToContext, function (context, subKey) {
64
77
  // I know...
65
78
  context.___obs_subkeys = context.___obs_subkeys || [];
package/dist/Store.js CHANGED
@@ -359,6 +359,9 @@ var Store = exports["default"] = /*#__PURE__*/function () {
359
359
  key: "hasChanged",
360
360
  value: function hasChanged(type, object) {
361
361
  var _this8 = this;
362
+ if (!this.models[type]) {
363
+ throw new Error("Not valid model type");
364
+ }
362
365
  var _hasChanged = function _hasChanged(type, object) {
363
366
  var obj = _this8.models[type].storedObjects[object.getId()];
364
367
  return !obj || obj.fingerprint !== obj.object.getFingerprint();
@@ -367,7 +370,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
367
370
  return _hasChanged(type, object);
368
371
  } else {
369
372
  return Object.values(this.models[type].storedObjects).some(function (i) {
370
- return _hasChanged(type, i);
373
+ return _hasChanged(type, i.object);
371
374
  });
372
375
  }
373
376
  }