@cleanweb/react 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,11 @@
1
1
  declare class MergedState<TState extends object> {
2
- static refresh<TState extends object>(this: MergedState<TState>): void;
2
+ static useRefresh<TState extends object>(this: MergedState<TState>): void;
3
3
  reservedKeys: string[];
4
4
  valueKeys: string[];
5
5
  private _initialValues_;
6
6
  private _values_;
7
7
  private setState;
8
8
  private _setters_;
9
- private useRetrieveState;
10
9
  get put(): { [Key in keyof TState]: (value: TState[Key]) => void; };
11
10
  get initialState(): TState;
12
11
  constructor(initialState: TState);
@@ -19,10 +19,6 @@ var MergedState = /** @class */ (function () {
19
19
  this._initialValues_ = {};
20
20
  this._values_ = {};
21
21
  this._setters_ = {};
22
- this.useRetrieveState = function () {
23
- var _a;
24
- _a = (0, react_1.useState)(_this.initialState), _this._values_ = _a[0], _this.setState = _a[1];
25
- };
26
22
  this.putMany = function (newValues) {
27
23
  _this.setState(__assign(__assign({}, _this._values_), newValues));
28
24
  };
@@ -52,8 +48,9 @@ var MergedState = /** @class */ (function () {
52
48
  });
53
49
  });
54
50
  }
55
- MergedState.refresh = function () {
56
- this.useRetrieveState();
51
+ MergedState.useRefresh = function () {
52
+ var _a;
53
+ _a = (0, react_1.useState)(this.initialState), this._values_ = _a[0], this.setState = _a[1];
57
54
  };
58
55
  Object.defineProperty(MergedState.prototype, "put", {
59
56
  get: function () {
@@ -73,7 +70,7 @@ var MergedState = /** @class */ (function () {
73
70
  }());
74
71
  var useMergedState = function (initialState) {
75
72
  var cleanState = (0, react_1.useMemo)(function () { return new MergedState(initialState); }, []);
76
- MergedState.refresh.call(cleanState);
73
+ MergedState.useRefresh.call(cleanState);
77
74
  return cleanState;
78
75
  };
79
76
  exports.useMergedState = useMergedState;
@@ -1,24 +1,16 @@
1
- type TUseStateArray<TState extends object> = [
2
- val: TState[keyof TState],
3
- setter: (val: TState[keyof TState]) => void
4
- ];
5
- type TUseStateResponses<TState extends object> = {
6
- [Key in keyof TState]: TUseStateArray<TState>;
7
- };
8
1
  declare class CleanStateBase<TState extends object> {
9
- static update: ICleanStateClass['update'];
10
2
  reservedKeys: string[];
11
3
  valueKeys: string[];
12
4
  private _values_;
5
+ private _initialValues_;
13
6
  private _setters_;
7
+ constructor(initialState: TState);
8
+ static update: <TState_1 extends object>(this: CleanStateBase<TState_1>) => void;
14
9
  get put(): { [Key in keyof TState]: (value: TState[Key]) => void; };
15
- constructor();
10
+ get initialState(): TState;
16
11
  putMany: (newValues: Partial<TState>) => void;
17
12
  }
18
13
  type TCleanStateInstance<TState extends object> = TState & CleanStateBase<TState>;
19
- interface ICleanStateClass {
20
- update: <TState extends object>(this: CleanStateBase<TState>, stateAndSetters: TUseStateResponses<TState>) => void;
21
- }
22
14
  export type TCleanState<TState extends object> = TCleanStateInstance<TState>;
23
15
  type Func = (...params: any[]) => any;
24
16
  type UseCleanState = <TState extends object, TProps extends object = object>(_initialState: ((props?: TProps) => TState) | TState, // TStateObjOrFactory,
@@ -14,9 +14,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.useMountState = exports.useCleanState = void 0;
15
15
  var react_1 = require("react");
16
16
  var CleanStateBase = /** @class */ (function () {
17
- function CleanStateBase() {
17
+ function CleanStateBase(initialState) {
18
18
  var _this = this;
19
- this.valueKeys = [];
20
19
  this._values_ = {};
21
20
  this._setters_ = {};
22
21
  this.putMany = function (newValues) {
@@ -26,22 +25,20 @@ var CleanStateBase = /** @class */ (function () {
26
25
  });
27
26
  };
28
27
  this.reservedKeys = Object.keys(this);
29
- }
30
- Object.defineProperty(CleanStateBase.prototype, "put", {
31
- get: function () {
32
- return __assign({}, this._setters_);
33
- },
34
- enumerable: false,
35
- configurable: true
36
- });
37
- CleanStateBase.update = function update(stateAndSetters) {
38
- var _this = this;
39
- Object.entries(stateAndSetters).forEach(function (_a) {
40
- var key = _a[0], responseFromUseState = _a[1];
28
+ /**
29
+ * The keys from the initial state object.
30
+ * By capturing and storing the value once, we ensure that any potential changes to the object,
31
+ * or irregularities in the order of keys returned by Object.keys,
32
+ * will not affect the order of subsequent useState calls.
33
+ * Only keys provided on the initial call will be recognized,
34
+ * since CleanState is instantiated only once with useMemo,
35
+ * and they will always be processed in a consistent order during rerenders.
36
+ */
37
+ this.valueKeys = Object.keys(initialState);
38
+ this._initialValues_ = __assign({}, initialState);
39
+ this.valueKeys.forEach(function (key) {
41
40
  if (_this.reservedKeys.includes(key))
42
41
  throw new Error("The name \"".concat(key, "\" is reserved by CleanState and cannot be used to index state variables. Please use a different key."));
43
- _this.valueKeys.push(key);
44
- _this._values_[key] = responseFromUseState[0], _this._setters_[key] = responseFromUseState[1];
45
42
  var self = _this;
46
43
  Object.defineProperty(_this, key, {
47
44
  get: function () {
@@ -53,39 +50,52 @@ var CleanStateBase = /** @class */ (function () {
53
50
  enumerable: true,
54
51
  });
55
52
  });
53
+ }
54
+ Object.defineProperty(CleanStateBase.prototype, "put", {
55
+ get: function () {
56
+ return __assign({}, this._setters_);
57
+ },
58
+ enumerable: false,
59
+ configurable: true
60
+ });
61
+ Object.defineProperty(CleanStateBase.prototype, "initialState", {
62
+ get: function () {
63
+ return __assign({}, this._initialValues_);
64
+ },
65
+ enumerable: false,
66
+ configurable: true
67
+ });
68
+ CleanStateBase.update = function update() {
69
+ var _this = this;
70
+ if (!(this instanceof CleanState))
71
+ throw new Error('CleanState.update must be called with `this` value set to a CleanState instance. Did you forget to use `.call` or `.apply`? Example: CleanState.update.call(cleanState);');
72
+ /**
73
+ * Linters complain about the use of a React hook within a loop because:
74
+ * > By following this rule, you ensure that Hooks are called in the same order each time a component renders.
75
+ * > That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
76
+ * To resolve this, we're calling `useState` via an alias `retrieveState`.
77
+ * Bypassing this rule is safe here because `useCleanState` is a special case,
78
+ * and it guarantees that the same useState calls will be made on every render in the exact same order.
79
+ * Therefore, it is safe to silence the linters, and required for this implementation to work smoothly.
80
+ */
81
+ var retrieveState = react_1.useState;
82
+ this.valueKeys.forEach(function (key) {
83
+ var _a;
84
+ _a = retrieveState(_this.initialState[key]), _this._values_[key] = _a[0], _this._setters_[key] = _a[1];
85
+ });
86
+ /* Object.entries<TUseStateArray<TState>>(stateAndSetters).forEach(([key, responseFromUseState]) => {
87
+ [this._values_[key], this._setters_[key]] = responseFromUseState;
88
+ }); */
56
89
  // return this;
57
90
  };
58
91
  return CleanStateBase;
59
92
  }());
60
93
  ;
61
- var a;
62
94
  var CleanState = CleanStateBase;
63
- var na = new CleanState();
64
- /**
65
- * Linters complain about the use of a React hook within a loop because:
66
- * > By following this rule, you ensure that Hooks are called in the same order each time a component renders.
67
- * > That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
68
- * To resolve this, we're calling `useState` via an alias `retrieveState`.
69
- * Bypassing this rule is safe here because `useCleanState` is a special case,
70
- * and it guarantees that the same useState calls will be made on every render in the exact same order.
71
- * Therefore, it is safe to silence the linters, and required for this implementation to work smoothly.
72
- */
73
- var retrieveState = react_1.useState;
74
95
  var useCleanState = function (_initialState, props) {
75
- var initialState = typeof _initialState === 'function' ? _initialState(props) : _initialState;
76
- // props?.s
77
- var cleanState = (0, react_1.useMemo)(function () { return new CleanState(); }, []);
78
- var stateKeys = Object.keys(initialState);
79
- var initialCount = (0, react_1.useState)(stateKeys.length)[0];
80
- if (stateKeys.length !== initialCount) {
81
- throw new Error('The keys in your state object must be consistent throughout your components lifetime. Look up "rules of hooks" for more context.');
82
- }
83
- var stateAndSetters = {};
84
- for (var _i = 0, stateKeys_1 = stateKeys; _i < stateKeys_1.length; _i++) {
85
- var key = stateKeys_1[_i];
86
- stateAndSetters[key] = retrieveState(initialState[key]);
87
- }
88
- CleanState.update.call(cleanState, stateAndSetters);
96
+ var initialState = typeof _initialState === 'function' ? (0, react_1.useMemo)(function () { return _initialState(props); }, []) : _initialState;
97
+ var cleanState = (0, react_1.useMemo)(function () { return new CleanState(initialState); }, []);
98
+ CleanState.update.call(cleanState);
89
99
  return cleanState;
90
100
  };
91
101
  exports.useCleanState = useCleanState;
package/build/index.js CHANGED
@@ -17,13 +17,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./classy"), exports);
18
18
  // PS: Document component inheritance pattern with lifecycle callback arrays and namespaces.
19
19
  // Due to react's remounting behaviour, components must externally track when some logic has run, if it really really must only ever run once per mounted instance. Tricky to get right for components that may have multiple instance rendered simultaneously at different parts of a page.
20
- // Note: There is an alternative clean-state implementation that uses a single useState call and passes the clean state instance.
21
- // Then when a state setter is used, it mutates the cleanstate object, then calls setState on the updated cleanstate.
22
- // But setState might ignore calls with the same object ref as the existing state value, so perhaps create a new cleanstate
23
- // instance instead, spreading existing values with the changed values, and call setState with that.
24
- // It could be more performant as it would remove the need for looping over Object.keys in useCleanState.
25
- // Investigate this for a potential minor version update.
26
- // useCleanState => useState
20
+ // useCleanState => useState, separate call for each key
21
+ // useMergedState => useState, same call for all keys
27
22
  // useMethods => useCallback
28
23
  // useLogic => useCallback + all other hook calls.
29
24
  // useInstance => useLogic + lifecycle methods.
25
+ /*
26
+ - Write usage doc
27
+ - Push to git and publish to site
28
+ - Follow-up personal post on class component inheritance can be published on GH Pages from profile repo.
29
+ - Publish to NPM
30
+ - Finalize package and repo names, then post to Twitter.
31
+ */
32
+ /*
33
+ withFetchApi(baseUrl); To mimic axios.get and axios.post type calls.
34
+ @cleanweb/mem-store - Release global-store package here.
35
+ Use mem-store to cache requests in createApi(); Use md5 hashed url as key.
36
+ @todo Add simple persistence layer with indexed db.
37
+ @cleanweb/subscribable - To publish changes in the data to subscribers.
38
+ @cleanweb/reactive-data - To combine all 4.
39
+ */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -20,6 +20,7 @@
20
20
  "./base": "./build/base/index.js",
21
21
  "./classy": "./build/classy/index.js",
22
22
  "./state": "./build/base/state.js",
23
+ "./state/merged": "./build/base/merged-state.js",
23
24
  "./methods": "./build/base/methods.js",
24
25
  "./logic": "./build/classy/logic.js",
25
26
  "./instance": "./build/classy/instance.js",