@cleanweb/react 2.1.1 → 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 +21 -10
- package/build/base/methods.d.ts +0 -2
- package/build/base/methods.js +0 -2
- package/build/base/state/hooks.d.ts +3 -3
- package/build/base/state/hooks.js +3 -3
- package/build/classy/class/index.d.ts +17 -13
- package/build/classy/class/index.js +18 -15
- package/build/classy/instance/index.d.ts +38 -2
- package/build/classy/instance/index.js +37 -2
- package/build/classy/logic/index.d.ts +2 -0
- package/build/classy/logic/index.js +2 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +0 -8
- package/package.json +1 -1
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
|
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]()
|
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
|
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.
|
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
|
-
|
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) {
|
package/build/base/methods.d.ts
CHANGED
@@ -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;
|
package/build/base/methods.js
CHANGED
@@ -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 () {
|
@@ -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
|
-
* @
|
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
|
-
* @
|
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.
|
34
|
-
*
|
35
|
-
*
|
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
|
40
|
+
* @example Using a template function that returns JSX.
|
40
41
|
*
|
41
42
|
* ```tsx
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
43
|
+
* beforeRender = () => {
|
44
|
+
* return {
|
45
|
+
* title: `My Site | ${this.props.title}`,
|
46
|
+
* };
|
47
|
+
* }
|
48
|
+
* template = (ctx) => {
|
45
49
|
* return (
|
46
50
|
* <h1>
|
47
|
-
* {
|
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.
|
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.
|
56
|
-
*
|
57
|
-
*
|
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
|
62
|
+
* @example Using a template function that returns JSX.
|
62
63
|
*
|
63
64
|
* ```tsx
|
64
|
-
*
|
65
|
-
*
|
66
|
-
*
|
65
|
+
* beforeRender = () => {
|
66
|
+
* return {
|
67
|
+
* title: `My Site | ${this.props.title}`,
|
68
|
+
* };
|
69
|
+
* }
|
70
|
+
* template = (ctx) => {
|
67
71
|
* return (
|
68
72
|
* <h1>
|
69
|
-
* {
|
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;
|
package/build/index.d.ts
CHANGED
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
|
-
*/
|