@cleanweb/react 2.1.1-beta.3 → 2.1.2

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
@@ -55,7 +55,7 @@ const Button = (props) => {
55
55
 
56
56
  > **Note:** Each top-level key in your initial state object gets a separate call to `React.useState`, and `state.put[key]()` is a proxy for the setter function returned from `useState`. So using this hook is fundamentally the same as calling `useState` directly for each value. What `useCleanState` provides is a way to unify those values and a convenient API for updating them.
57
57
 
58
- [Read the `useCleanState` docs](https://cleanjsweb.github.io/neat-react) for more details.
58
+ [Read the `useCleanState` API docs](https://cleanjsweb.github.io/neat-react/functions/API.useCleanState.html) for more details.
59
59
 
60
60
  ### Methods
61
61
  The `useMethods` hook lets you manage the closures that your component uses in a separate class, keeping the body of the component clean and easier to read. With `useMethods`, your functions are not recreated on every render. Yet, every method of your component is guaranteed to always have access to the latest props and state without the need for a dependencty array.
@@ -110,10 +110,14 @@ const Button = (props) => {
110
110
  }
111
111
  ```
112
112
 
113
- [Read the `useMethods` docs]() for more details.
113
+ [Read the `useMethods` API docs](https://cleanjsweb.github.io/neat-react/functions/API.useMethods.html) for more details.
114
+
115
+ <small>Discussion: [Reasoning behind `useMethods`](https://cleanjsweb.github.io/neat-react/documents/Methods_Hook.html).</small>
114
116
 
115
117
  ### Logic
116
- The `useLogic` hook is an expansion of `useMethods`, with the aim of being a more holistic solution. It combines the functionality of `useCleanState` and `useMethods`. In addition, it allows you to externalize _all_ of your component's logic, not just closures and state. Essentially, this means being able to call hooks from within the class, rather than having to do so within the component body.
118
+ The `useLogic` hook is an expansion of [`useMethods`](#methods), with the aim of being a more holistic solution. It combines the functionality of [`useCleanState`](#clean-state) and [`useMethods`](#methods).
119
+
120
+ In addition, it allows you to externalize _all_ of your component's logic, not just closures and state. Essentially, this means being able to call hooks from within the class, rather than having to do so within the component body.
117
121
 
118
122
  ```jsx
119
123
  class ButtonLogic {
@@ -164,10 +168,13 @@ const Button = (props) => {
164
168
  }
165
169
  ```
166
170
 
167
- [Read the `useLogic` docs]() for more details.
171
+ [Read the `useLogic` docs](https://cleanjsweb.github.io/neat-react/documents/Logic_Hook.html).
172
+
168
173
 
169
174
  ### Lifecycle (`useInstance`)
170
- The `useInstance` hook provides a simple approach for working with your components lifecycle. It includes all the features of [`useLogic`](#logic), and adds special lifecycle methods. This gives you a declarative way to run certain code at specific stages of your component's life time. You will likely find this to be less error prone and much easier to reason about than the imperative approach of using React's hooks directly.
175
+ The `useInstance` hook provides a simple approach for working with your component's lifecycle. It includes all the features of [`useLogic`](#logic), and adds special lifecycle methods.
176
+
177
+ This gives you a declarative way to run certain code at specific stages of your component's life time. You will likely find this to be less error prone and much easier to reason about than the imperative approach of using React's hooks directly.
171
178
 
172
179
  ```jsx
173
180
  /** Button Component Class. */
@@ -250,7 +257,10 @@ const Button = (props) => {
250
257
  }
251
258
  ```
252
259
 
253
- [Read the `useInstance` docs]() for more details.
260
+ [Read the `useInstance` API docs](https://cleanjsweb.github.io/neat-react/functions/API.useInstance.html) for more details.
261
+
262
+ <small>For a lengthier discussion on the reasoning behind the `useInstance` hook, see the [`useInstance` discussion doc](https://cleanjsweb.github.io/neat-react/documents/Instance_Hook.html).
263
+
254
264
 
255
265
  ### Class Component
256
266
  With `useInstance`, pretty much every aspect of your component is now part of the class, except for the JSX template. The `ClassComponent` class takes that final step and provides a fully integrated class-based React component.
@@ -304,10 +314,13 @@ export default Button.RC;
304
314
  // Or render directly with `<Button.RC />`.
305
315
  ```
306
316
 
307
- Every class derived from the base `ClassComponent` is not itself a React component. Instead, it has a static `extract()` method (also aliased as `FC()` for "Function Component") which returns a function component that can be rendered like any other React component. Each instance of this function component mounted in the React tree creates it's own separate instance of your `ClassComponent` class. To make it easier to use the class component directly, you should create a static property that holds the function component returned by `extract`. The recommended convention is to use the name `RC` (for "React Component"). Such a class can then easily be rendered as JSX by writing `<MyComponent.RC />`.
317
+ Every class derived from the base `ClassComponent` is not itself a React component. Instead, it has a static `extract()` method (also aliased as `FC()` for "Function Component") which returns a function component that can be rendered like any other React component. Each instance of this function component mounted in the React tree creates it's own separate instance of your `ClassComponent` class.
308
318
 
309
- [Read the `ClassComponent` docs]() for more details.
319
+ To make it easier to use the class component directly, you should create a static property that holds the function component returned by `extract`. The recommended convention is to use the name `RC` (for "React Component"). Such a class can then easily be rendered as JSX by writing `<MyComponent.RC />`.
310
320
 
321
+ [Read the `ClassComponent` API docs](https://cleanjsweb.github.io/neat-react/classes/API.ClassComponent.html) for more details.
322
+
323
+ <small>For a discussion on how this works, and a comparison with React's older `React.Component` class, see the [`ClassComponent` discussion doc](https://cleanjsweb.github.io/neat-react/documents/Class_Component.html).</small>
311
324
 
312
325
  ### Other Exports
313
326
 
@@ -315,8 +328,6 @@ Every class derived from the base `ClassComponent` is not itself a React compone
315
328
  If you simply want to use hooks in your `React.Component` class without having to rewrite anything, this package also exports a `<Use>` component that helps you achieve this easily. Here's how to use it.
316
329
 
317
330
  ```jsx
318
- import { useGlobalStore } from '@/hooks/store';
319
-
320
331
  class Button extends React.Component {
321
332
  syncGlobalStore = ([store, updateStore]) => {
322
333
  if (this.state.userId !== store.userId) {
@@ -24,11 +24,9 @@ type UseMethods = {
24
24
  <Class extends typeof ComponentMethods<NeverObject, null>>(Methods: Class & Constructor<InstanceType<Class>>): InstanceType<Class>;
25
25
  };
26
26
  /**
27
- * @summary
28
27
  * Returns an instance of the provided class,
29
28
  * with the state and props arguments added as instance members.
30
29
  *
31
- * @remarks
32
30
  * `state` should be an instance of `CleanState` created with {@link useCleanState}.
33
31
  */
34
32
  declare const useMethods: UseMethods;
@@ -36,11 +36,9 @@ var ComponentMethods = /** @class */ (function () {
36
36
  exports.ComponentMethods = ComponentMethods;
37
37
  ;
38
38
  /**
39
- * @summary
40
39
  * Returns an instance of the provided class,
41
40
  * with the state and props arguments added as instance members.
42
41
  *
43
- * @remarks
44
42
  * `state` should be an instance of `CleanState` created with {@link useCleanState}.
45
43
  */
46
44
  var useMethods = function () {
@@ -71,8 +69,8 @@ var useMethods = function () {
71
69
  'Note that this mechanism only works in the `development` environment during HMR.',
72
70
  'In production, the class argument will be ignored after the first render.\n\n',
73
71
  'If this wasn\'t an HMR update, you should refactor your code to make sure',
74
- 'all clean-react hooks receive the same class object on every render.'
75
- ].join());
72
+ 'all clean-react hooks receive the same class argument on every render.'
73
+ ].join(' '));
76
74
  var oldInstance = instanceRef.current;
77
75
  var hmrPreserveKeys = __spreadArray(__spreadArray([], latestInstance._hmrPreserveKeys, true), [
78
76
  'state', 'props',
@@ -1,12 +1,12 @@
1
1
  import { TUseCleanState } from './hook-types';
2
2
  /**
3
- * @summary
4
3
  * Creates a state object, which includes the provided values,
5
4
  * as well as helper methods for updating those values and automatically
6
5
  * rerendering your component's UI to reflect said updates.
7
6
  *
8
- * @remarks
9
- * Uses {@link React.useState} under the hook, with a separate call
7
+ * Uses {@link React.useState} under the hood, with a separate call
10
8
  * to `useState` for each top-level key in the provided object.
9
+ *
10
+ * Discussion: [When to use `cleanState`](https://cleanjsweb.github.io/neat-react/documents/Clean_State.html).
11
11
  */
12
12
  export declare const useCleanState: TUseCleanState;
@@ -4,14 +4,14 @@ exports.useCleanState = void 0;
4
4
  var react_1 = require("react");
5
5
  var class_1 = require("./class");
6
6
  /**
7
- * @summary
8
7
  * Creates a state object, which includes the provided values,
9
8
  * as well as helper methods for updating those values and automatically
10
9
  * rerendering your component's UI to reflect said updates.
11
10
  *
12
- * @remarks
13
- * Uses {@link React.useState} under the hook, with a separate call
11
+ * Uses {@link React.useState} under the hood, with a separate call
14
12
  * to `useState` for each top-level key in the provided object.
13
+ *
14
+ * Discussion: [When to use `cleanState`](https://cleanjsweb.github.io/neat-react/documents/Clean_State.html).
15
15
  */
16
16
  var useCleanState = function (_initialState) {
17
17
  var props = [];
@@ -23,29 +23,34 @@ export declare class ClassComponent<TProps extends TPropsBase = null> extends Co
23
23
  * Analogous to {@link React.Component.render}. A function that returns
24
24
  * your component's JSX template.
25
25
  *
26
- * You should place most logic that would usually go here
27
- * in {@link ComponentInstance.beforeRender | `beforeRender`} instead.
28
- * This helps to separate concerns and keep the template itself clean.
29
- *
30
26
  * ******
31
27
  *
32
28
  * Ideally the template method should only be concerned with defining the HTML/JSX structure of
33
- * your component's UI. This may include destructuring nested instance members
34
- * into more easily accessible local variables, or some simple transformation of data from props/state
35
- * into a more appropriate format for display.
29
+ * your component's UI.
30
+ *
31
+ * If you need to transform some data for display,
32
+ * do so in [beforeRender]({@link ComponentInstance.beforeRender}),
33
+ * and return an object with transformed data that can be rendered directly.
34
+ *
35
+ * The returned object will be passed to your template method
36
+ * as a `context` object.
36
37
  *
37
38
  * ******
38
39
  *
39
- * @example <caption>Using a template function that returns JSX.</caption>
40
+ * @example Using a template function that returns JSX.
40
41
  *
41
42
  * ```tsx
42
- * template = () => {
43
- * const { title } = this.props;
44
- *
43
+ * beforeRender = () => {
44
+ * return {
45
+ * title: `My Site | ${this.props.title}`,
46
+ * };
47
+ * }
48
+ * template = (ctx) => {
45
49
  * return (
46
50
  * <h1>
47
- * {this.props.title}
51
+ * {ctx.title}
48
52
  * </h1>
53
+ * <p>{this.props.description}</p>
49
54
  * );
50
55
  * }
51
56
  * ```
@@ -91,7 +96,6 @@ export declare class ClassComponent<TProps extends TPropsBase = null> extends Co
91
96
  static readonly FC: Extractor;
92
97
  }
93
98
  export { ClassComponent as Component };
94
- export { Use } from '../../helpers/use-component';
95
99
  /** /
96
100
  testing: {
97
101
  const a: object = {b: ''};
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
15
15
  };
16
16
  })();
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.Use = exports.Component = exports.ClassComponent = void 0;
18
+ exports.Component = exports.ClassComponent = void 0;
19
19
  var react_1 = require("react");
20
20
  var instance_1 = require("../instance");
21
21
  var function_name_1 = require("./utils/function-name");
@@ -45,29 +45,34 @@ var ClassComponent = /** @class */ (function (_super) {
45
45
  * Analogous to {@link React.Component.render}. A function that returns
46
46
  * your component's JSX template.
47
47
  *
48
- * You should place most logic that would usually go here
49
- * in {@link ComponentInstance.beforeRender | `beforeRender`} instead.
50
- * This helps to separate concerns and keep the template itself clean.
51
- *
52
48
  * ******
53
49
  *
54
50
  * Ideally the template method should only be concerned with defining the HTML/JSX structure of
55
- * your component's UI. This may include destructuring nested instance members
56
- * into more easily accessible local variables, or some simple transformation of data from props/state
57
- * into a more appropriate format for display.
51
+ * your component's UI.
52
+ *
53
+ * If you need to transform some data for display,
54
+ * do so in [beforeRender]({@link ComponentInstance.beforeRender}),
55
+ * and return an object with transformed data that can be rendered directly.
56
+ *
57
+ * The returned object will be passed to your template method
58
+ * as a `context` object.
58
59
  *
59
60
  * ******
60
61
  *
61
- * @example <caption>Using a template function that returns JSX.</caption>
62
+ * @example Using a template function that returns JSX.
62
63
  *
63
64
  * ```tsx
64
- * template = () => {
65
- * const { title } = this.props;
66
- *
65
+ * beforeRender = () => {
66
+ * return {
67
+ * title: `My Site | ${this.props.title}`,
68
+ * };
69
+ * }
70
+ * template = (ctx) => {
67
71
  * return (
68
72
  * <h1>
69
- * {this.props.title}
73
+ * {ctx.title}
70
74
  * </h1>
75
+ * <p>{this.props.description}</p>
71
76
  * );
72
77
  * }
73
78
  * ```
@@ -137,8 +142,6 @@ var ClassComponent = /** @class */ (function (_super) {
137
142
  }(instance_1.ComponentInstance));
138
143
  exports.ClassComponent = ClassComponent;
139
144
  exports.Component = ClassComponent;
140
- var use_component_1 = require("../../helpers/use-component");
141
- Object.defineProperty(exports, "Use", { enumerable: true, get: function () { return use_component_1.Use; } });
142
145
  /** /
143
146
  testing: {
144
147
  const a: object = {b: ''};
@@ -31,12 +31,50 @@ export declare class ComponentInstance<TProps extends TPropsBase = null> extends
31
31
  * Uses `useEffect()` under the hood.
32
32
  */
33
33
  onMount: AsyncAllowedEffectCallback;
34
+ /** @see {@link templateContext} */
34
35
  private _templateContext;
36
+ /**
37
+ * Holds the object returned by {@link beforeRender}.
38
+ *
39
+ * This is useful when you need to render some state or props
40
+ * in a transformed format. Put the transformation logic
41
+ * in {@link beforeRender} to the keep the function component
42
+ * template clean.
43
+ *
44
+ * ******
45
+ *
46
+ * @example Using templateContext.
47
+ *
48
+ * ```tsx
49
+ * class MyComponentLogic extends ComponentInstance {
50
+ * beforeRender = () => {
51
+ * const title = `My Site | ${this.props.title}`;
52
+ * return { title };
53
+ * }
54
+ * }
55
+ * const MyComponent = (props) => {
56
+ * const self = useInstance(MyComponentLogic, props);
57
+ * const { template: ctx, state } = self;
58
+ *
59
+ * return (
60
+ * <h1>
61
+ * {ctx.title}
62
+ * </h1>
63
+ * <p>{props.description}</p>
64
+ * );
65
+ * }
66
+ * ```
67
+ */
35
68
  get templateContext(): ReturnType<this["beforeRender"]>;
36
69
  /**
37
70
  * Runs _before_ every render cycle, including the first.
38
71
  * Useful for logic that is involved in determining what to render.
39
72
  *
73
+ * This is the ideal place to transform data for display.
74
+ * Return the transformed data in an object, and the object will
75
+ * availble as [`self.templateContext`]({@link templateContext})
76
+ * for use in your JSX template.
77
+ *
40
78
  * PS: You can conditionally update state from here, but with certain caveats.
41
79
  * {@link https://react.dev/reference/react/useState#storing-information-from-previous-renders | See the React docs for more details}.
42
80
  */
@@ -59,7 +97,6 @@ export declare class ComponentInstance<TProps extends TPropsBase = null> extends
59
97
  cleanUp: IVoidFunction;
60
98
  }
61
99
  /**
62
- * @summary
63
100
  * Enables full separation of concerns between a React components template
64
101
  * and all of the logic that drives it.
65
102
  *
@@ -70,7 +107,6 @@ export declare class ComponentInstance<TProps extends TPropsBase = null> extends
70
107
  * can be externalized from the function component itself,
71
108
  * and defined in a separate class.
72
109
  *
73
- * @remarks
74
110
  * The provided class should be a subclass of {@link ComponentInstance}.
75
111
  *
76
112
  * @privateRemarks
@@ -57,6 +57,11 @@ var ComponentInstance = /** @class */ (function (_super) {
57
57
  * Runs _before_ every render cycle, including the first.
58
58
  * Useful for logic that is involved in determining what to render.
59
59
  *
60
+ * This is the ideal place to transform data for display.
61
+ * Return the transformed data in an object, and the object will
62
+ * availble as [`self.templateContext`]({@link templateContext})
63
+ * for use in your JSX template.
64
+ *
60
65
  * PS: You can conditionally update state from here, but with certain caveats.
61
66
  * {@link https://react.dev/reference/react/useState#storing-information-from-previous-renders | See the React docs for more details}.
62
67
  */
@@ -80,6 +85,38 @@ var ComponentInstance = /** @class */ (function (_super) {
80
85
  return _this;
81
86
  }
82
87
  Object.defineProperty(ComponentInstance.prototype, "templateContext", {
88
+ /**
89
+ * Holds the object returned by {@link beforeRender}.
90
+ *
91
+ * This is useful when you need to render some state or props
92
+ * in a transformed format. Put the transformation logic
93
+ * in {@link beforeRender} to the keep the function component
94
+ * template clean.
95
+ *
96
+ * ******
97
+ *
98
+ * @example Using templateContext.
99
+ *
100
+ * ```tsx
101
+ * class MyComponentLogic extends ComponentInstance {
102
+ * beforeRender = () => {
103
+ * const title = `My Site | ${this.props.title}`;
104
+ * return { title };
105
+ * }
106
+ * }
107
+ * const MyComponent = (props) => {
108
+ * const self = useInstance(MyComponentLogic, props);
109
+ * const { template: ctx, state } = self;
110
+ *
111
+ * return (
112
+ * <h1>
113
+ * {ctx.title}
114
+ * </h1>
115
+ * <p>{props.description}</p>
116
+ * );
117
+ * }
118
+ * ```
119
+ */
83
120
  get: function () {
84
121
  return this._templateContext;
85
122
  },
@@ -91,7 +128,6 @@ var ComponentInstance = /** @class */ (function (_super) {
91
128
  exports.ComponentInstance = ComponentInstance;
92
129
  ;
93
130
  /**
94
- * @summary
95
131
  * Enables full separation of concerns between a React components template
96
132
  * and all of the logic that drives it.
97
133
  *
@@ -102,7 +138,6 @@ exports.ComponentInstance = ComponentInstance;
102
138
  * can be externalized from the function component itself,
103
139
  * and defined in a separate class.
104
140
  *
105
- * @remarks
106
141
  * The provided class should be a subclass of {@link ComponentInstance}.
107
142
  *
108
143
  * @privateRemarks
@@ -66,6 +66,8 @@ export declare class ComponentLogic<TProps extends TPropsBase = null> {
66
66
  * encapsulates hook calls with the special {@link ComponentLogic.useHooks | `useHooks`} method.
67
67
  *
68
68
  * The class argument must be a subclass of {@link ComponentLogic}.
69
+ *
70
+ * @see https://cleanjsweb.github.io/neat-react/functions/API.useLogic.html
69
71
  */
70
72
  export declare const useLogic: UseLogic;
71
73
  /** /
@@ -57,6 +57,8 @@ exports.ComponentLogic = ComponentLogic;
57
57
  * encapsulates hook calls with the special {@link ComponentLogic.useHooks | `useHooks`} method.
58
58
  *
59
59
  * The class argument must be a subclass of {@link ComponentLogic}.
60
+ *
61
+ * @see https://cleanjsweb.github.io/neat-react/functions/API.useLogic.html
60
62
  */
61
63
  var useLogic = function () {
62
64
  var _a, _b;
@@ -79,8 +81,8 @@ var useLogic = function () {
79
81
  'Note that this mechanism only works in the `development` environment during HMR.',
80
82
  'In production, the class argument will be ignored after the first render.\n\n',
81
83
  'If this wasn\'t an HMR update, you should refactor your code to make sure',
82
- 'all clean-react hooks receive the same class object on every render.'
83
- ].join());
84
+ 'all clean-react hooks receive the same class argument on every render.'
85
+ ].join(' '));
84
86
  var oldInstance_1 = instanceRef.current;
85
87
  var hmrPreserveKeys = __spreadArray(__spreadArray([], latestInstance._hmrPreserveKeys, true), [
86
88
  'state', 'props', 'hooks',
package/build/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './classy';
2
2
  export * from './base';
3
3
  export * from './helpers';
4
+ export type { EmptyObject, NeverObject };
package/build/index.js CHANGED
@@ -17,11 +17,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./classy"), exports);
18
18
  __exportStar(require("./base"), exports);
19
19
  __exportStar(require("./helpers"), exports);
20
- /*
21
- withFetchApi(baseUrl); To mimic axios.get and axios.post type calls.
22
- @cleanweb/mem-store - Release global-store package here.
23
- Use mem-store to cache requests in withFetchApi(); Use md5 hashed url+body as key.
24
- @todo Add simple persistence layer with indexed db.
25
- @cleanweb/subscribable - To publish changes in the data to subscribers.
26
- @cleanweb/reactive-data - To combine all 4.
27
- */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "2.1.1-beta.3",
3
+ "version": "2.1.2",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"