reaction-hooks 1.0.1 → 1.0.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 +51 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@ Hooks for [Reaction](https://github.com/djalbat/reaction).
|
|
|
4
4
|
|
|
5
5
|
These are inspired by React's hooks but do not follow them slavishly. Three are three available:
|
|
6
6
|
|
|
7
|
-
* `useState()` A state management hook that does indeed
|
|
8
|
-
* `useContext()` A hook that leverages contexts in order to enable
|
|
9
|
-
* `useEffects()` A hook
|
|
7
|
+
* `useState()` A state management hook that does indeed slavishly follow React's hook of the same name. It also supports created classes and components, however.
|
|
8
|
+
* `useContext()` A hook that leverages contexts in order to enable directly related components to communicate. Typically component methods are passed via the context so that one component can call the methods of another.
|
|
9
|
+
* `useEffects()` A hook based around Reaction's update functionality in order to enable components to communicate no matter how they are related. It is also possible for components to communicate with other parts of an application and vice-versa using effects.
|
|
10
10
|
|
|
11
|
-
The `useEffects()` hook in fact bears very little resemblance to React's hook of the same name and is more akin to [Inference](https://github.com/djalbat/inference)
|
|
11
|
+
The `useEffects()` hook in fact bears very little resemblance to React's hook of the same name and is more akin to [Inference](https://github.com/djalbat/inference) albeit without the rules.
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -28,7 +28,7 @@ You can also run a development server, see the section on building later on.
|
|
|
28
28
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
|
-
The
|
|
31
|
+
The hooks are imported thus:
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
import { useState, useContext, useEffects } from "reaction-hooks";
|
|
@@ -44,11 +44,25 @@ Detailed usages are outlined in the recommanded patterns section that follows th
|
|
|
44
44
|
|
|
45
45
|
## Example
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
There is a small development server that can be run from within the project's directory with the following command:
|
|
48
|
+
|
|
49
|
+
npm start
|
|
50
|
+
|
|
51
|
+
The example will then be available at the following URL:
|
|
52
|
+
|
|
53
|
+
http://localhost:8888
|
|
54
|
+
|
|
55
|
+
The source for the example can be found in the `src/example.js` file and corresponding`src/example` folder. You are encouraged to try the example whilst reading what follows. You can rebuild it on the fly with the following command:
|
|
56
|
+
|
|
57
|
+
npm run watch-debug
|
|
58
|
+
|
|
59
|
+
The development server will reload the page whenever you make changes.
|
|
60
|
+
|
|
61
|
+
One last thing to bear in mind is that this package is included by way of a relative rather than a package import. If you are importing it into your own application, however, you should use the standard package import.
|
|
48
62
|
|
|
49
63
|
## Recommended patterns
|
|
50
64
|
|
|
51
|
-
Each of the hooks are covered with the listings closely matching the example code.
|
|
65
|
+
Each of the hooks are covered in turn with the listings closely matching the example code.
|
|
52
66
|
|
|
53
67
|
### `useState()`
|
|
54
68
|
|
|
@@ -73,9 +87,9 @@ const FunctionUseStateParagraph = (props, context, update, element) => {
|
|
|
73
87
|
```
|
|
74
88
|
Note that the last of the four function arguments is a reference to the function's corresponding element. The details are unimportant, however this reference must be passed as the first argument of the `useState()` call. Otherwise the usage is entirely analogous to the corresponding React hook.
|
|
75
89
|
|
|
76
|
-
Because the `useState()` hook is passed a reference to the corresponding element
|
|
90
|
+
Because the `useState()` hook is passed a reference to the corresponding element it can also support created classes and components, which also both have corresponding underlying elements.
|
|
77
91
|
|
|
78
|
-
|
|
92
|
+
To continue, the second way is with created classes. The name is a misnomer as they are not classes at all. With the advent of components they rarely if ever used, nonetheless they continue to be supported:
|
|
79
93
|
|
|
80
94
|
```
|
|
81
95
|
const { createClass } = React;
|
|
@@ -97,7 +111,7 @@ const CreateClassUseStateParagraph = createClass({
|
|
|
97
111
|
});
|
|
98
112
|
```
|
|
99
113
|
|
|
100
|
-
|
|
114
|
+
Note that the `useState()` call takes place within the `render()` function.
|
|
101
115
|
|
|
102
116
|
Lastly, genuine components, which are treated identically:
|
|
103
117
|
|
|
@@ -121,13 +135,13 @@ export default class ComponentUseStateParagraph extends Component {
|
|
|
121
135
|
}
|
|
122
136
|
```
|
|
123
137
|
|
|
124
|
-
Of course created classes and components support state without the need for a hook.
|
|
138
|
+
Of course created classes and components support state without the need for a hook.
|
|
125
139
|
|
|
126
140
|
### `useContext()`
|
|
127
141
|
|
|
128
142
|
This hook can be used comprehensively to share information, most likely methods, between components and the like that are directly related in the DOM. What this means is that in order for one component to share information with another it must be a descendant of the other or vice-versa. Since this hook leverages contexts, perhaps this is not so surprising. In fact another lifecycle method, namely the `childContextSet()`lifecycle method, was added to Reaction in order to support it.
|
|
129
143
|
|
|
130
|
-
At the topmost level of the example component both this lifecycle method and the
|
|
144
|
+
At the topmost level of the example component both this lifecycle method and the `setChildContext()` lifecycle method are utilised:
|
|
131
145
|
|
|
132
146
|
```
|
|
133
147
|
getChildContext(context) {
|
|
@@ -145,7 +159,7 @@ childContextSet(childContext) {
|
|
|
145
159
|
}
|
|
146
160
|
```
|
|
147
161
|
|
|
148
|
-
This usage is noteworthy because it does not make use of the `useContext()` hook at all. A more primitive approach is used here to emphasise the fact that the object created in the `createChildContext()` lifecycle method is not only passed down to the component's
|
|
162
|
+
This usage is noteworthy because it does not make use of the `useContext()` hook at all. A more primitive approach is used here to emphasise the fact that the object created in the `createChildContext()` lifecycle method is not only passed down to the component's descendants but is also precisely the one that is passed to the component's own `childContextSet()` lifecycle method.
|
|
149
163
|
|
|
150
164
|
A more conventional and indeed the recommended approach is to make use of the `useContetx()` hook in both lifecycle methods in each of its respective guises:
|
|
151
165
|
|
|
@@ -163,12 +177,12 @@ getChildContext(context) {
|
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
childContextSet(childContext) {
|
|
166
|
-
useContext(this
|
|
180
|
+
useContext(this, childContext);
|
|
167
181
|
}
|
|
168
182
|
```
|
|
169
|
-
In the `getChildContext()` lifecycle method, two of the topmost component's own methods are assigned to the context,
|
|
183
|
+
In the `getChildContext()` lifecycle method, two of the topmost component's own methods are assigned to the context, which is then passed to the component's descendants. Conversely, in the `childContextSet()` lifecycle method, whatever methods are on the child context at this point, which will have been assigned by the topmost component's descendants, are assigned to the topmost component.
|
|
170
184
|
|
|
171
|
-
Beginning to look down at the component's
|
|
185
|
+
Beginning to look down at the component's descendants, we see that the `GotItHeader` component adds two of its own methods to the context:
|
|
172
186
|
|
|
173
187
|
```
|
|
174
188
|
export default class GotItHeader extends Component {
|
|
@@ -187,7 +201,7 @@ export default class GotItHeader extends Component {
|
|
|
187
201
|
...
|
|
188
202
|
}
|
|
189
203
|
```
|
|
190
|
-
These will eventually be picked up by the topmost component in its aforementioned `childContextSet()` lifecycle method. Indeed we can see which methods of the component's
|
|
204
|
+
These will eventually be picked up by the topmost component in its aforementioned `childContextSet()` lifecycle method. Indeed we can see which methods of the component's descendants it ends up assigning to itself by looking at some of its other methods:
|
|
191
205
|
|
|
192
206
|
```
|
|
193
207
|
close() {
|
|
@@ -201,7 +215,20 @@ open() {
|
|
|
201
215
|
}
|
|
202
216
|
```
|
|
203
217
|
|
|
204
|
-
|
|
218
|
+
Therefore in order to be explicit we could have written:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
childContextSet(childContext) {
|
|
222
|
+
useContext(this, childContext, [
|
|
223
|
+
"showGotItDiv",
|
|
224
|
+
"hideGotItDiv",
|
|
225
|
+
"showGotItHeader",
|
|
226
|
+
"hideGotItHeader"
|
|
227
|
+
]);
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
By way of contrast, the descendant `OpenLinkButton` component grabs one of the topmost component's methods from the context and assigns it to itself. The method is then made use of in its own `render()` method:
|
|
205
232
|
|
|
206
233
|
```
|
|
207
234
|
export default class OpenLinkButton extends Component {
|
|
@@ -212,20 +239,21 @@ export default class OpenLinkButton extends Component {
|
|
|
212
239
|
}
|
|
213
240
|
|
|
214
241
|
render(update) {
|
|
215
|
-
const {
|
|
242
|
+
const { descendants } = this.props,
|
|
216
243
|
clickHandler = this.openLinkButtonClickHandler; ///
|
|
217
244
|
|
|
218
245
|
return (
|
|
219
246
|
|
|
220
247
|
<button className="open link" onClick={clickHandler}>
|
|
221
|
-
{
|
|
248
|
+
{descendants}
|
|
222
249
|
</button>
|
|
223
250
|
|
|
224
251
|
);
|
|
225
252
|
}
|
|
226
253
|
}
|
|
227
254
|
```
|
|
228
|
-
|
|
255
|
+
|
|
256
|
+
To summarise, the `useContext()` hook allows methods and the like to piggy back on the context, so to speak, so that components can pick them up and make use of them. Thus related components can call methods on each other without the need for more complex or indirect mechanisms such as message passing.
|
|
229
257
|
|
|
230
258
|
### `useEffects()`
|
|
231
259
|
|
|
@@ -310,9 +338,9 @@ updatehandler(update) {
|
|
|
310
338
|
}
|
|
311
339
|
```
|
|
312
340
|
|
|
313
|
-
Underneath the hood the `forceUpdate()` method will unmount the component's
|
|
341
|
+
Underneath the hood the `forceUpdate()` method will unmount the component's descendants and then mount the new descendants returned by invoking the component's `render()` method, which is passed the requisite update. In fact the update is just a plain old JavaScript object the single property of which is named after the effect and its value is the effect itself.
|
|
314
342
|
|
|
315
|
-
Finally, note that a component or indeed any part of the application can be configured to listen to several effects as additional arguments to the `useEffects()` hook, hence the use of the plural, in which cases the
|
|
343
|
+
Finally, note that a component or indeed any part of the application can be configured to listen to several effects as additional arguments to the `useEffects()` hook, hence the use of the plural, in which cases the encapsulation of each effect in a plain old JavaScript object becomes invaluable for ascertaining which effect has been emitted.
|
|
316
344
|
|
|
317
345
|
## Building
|
|
318
346
|
|
|
@@ -321,12 +349,6 @@ Automation is thanks to [npm scripts](https://docs.npmjs.com/misc/scripts), have
|
|
|
321
349
|
npm run build-debug
|
|
322
350
|
npm run watch-debug
|
|
323
351
|
|
|
324
|
-
You can also start a small development server:
|
|
325
|
-
|
|
326
|
-
npm start
|
|
327
|
-
|
|
328
|
-
The example will then be available at http://localhost:8888 and will reload automatically when changes are made.
|
|
329
|
-
|
|
330
352
|
## Contact
|
|
331
353
|
|
|
332
354
|
- james.smith@djalbat.com
|