react-chain-of-responsibility 0.3.0-main.e6dfb8e → 0.3.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 +37 -36
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,13 +14,13 @@ Click here for [our live demo](https://compulim.github.io/react-chain-of-respons
|
|
|
14
14
|
|
|
15
15
|
## How to use?
|
|
16
16
|
|
|
17
|
-
3 steps to adopt the chain of responsibility pattern.
|
|
17
|
+
There are 3 steps to adopt the chain of responsibility pattern.
|
|
18
18
|
|
|
19
19
|
1. [Create a chain](#create-a-chain)
|
|
20
20
|
1. [Register handlers in the chain](#register-handlers-in-the-chain)
|
|
21
21
|
1. [Make a render request](#make-a-render-request)
|
|
22
22
|
|
|
23
|
-
In this sample, we will use chain of responsibility pattern to create a file preview UI
|
|
23
|
+
In this sample, we will use chain of responsibility pattern to create a file preview UI to handle various file types.
|
|
24
24
|
|
|
25
25
|
### Create a chain
|
|
26
26
|
|
|
@@ -77,19 +77,19 @@ const Binary = ({ url }) => <a href={url}>{url}</a>;
|
|
|
77
77
|
const middleware = [asMiddleware(Image), asMiddleware(Video), asMiddleware(Binary)];
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
In this sample, 3 middleware
|
|
80
|
+
In this sample, 3 middleware will be registered in the chain. They will be called based on their order in the array:
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
1. `<Image>` will render `<img>` if content type is `'image/*'`, otherwise, will pass to next middleware
|
|
83
|
+
1. `<Video>` will render `<video>` if content type is `'video/*'`, otherwise, will pass to next middleware
|
|
84
|
+
1. `<Binary>` is a catch-all and will render as a link
|
|
85
85
|
|
|
86
|
-
Notes: props passed to `<Next
|
|
86
|
+
Notes: if props are passed to `<Next>`, they will override the original props. However, `request` cannot be overridden.
|
|
87
87
|
|
|
88
88
|
### Make a render request
|
|
89
89
|
|
|
90
|
-
Before calling any components or hooks, the `<Provider>` component must be
|
|
90
|
+
Before calling any components or hooks, the `<Provider>` component must be initialized with the chain.
|
|
91
91
|
|
|
92
|
-
When `<Proxy>` is being rendered, it will pass the `request` to the chain. The component returned from the chain will be rendered with `...props`. If no component is returned, it will
|
|
92
|
+
When `<Proxy>` is being rendered, it will pass the `request` to the chain. The component returned from the chain will be rendered with `...props`. If no component is returned, it will render `undefined`.
|
|
93
93
|
|
|
94
94
|
```tsx
|
|
95
95
|
render(
|
|
@@ -115,7 +115,7 @@ For advanced scenario with precise rendering control, use the `useBuildComponent
|
|
|
115
115
|
|
|
116
116
|
## How should I use?
|
|
117
117
|
|
|
118
|
-
Here are some recipes
|
|
118
|
+
Here are some recipes leveraging the chain of responsibility pattern for UI composition and customization.
|
|
119
119
|
|
|
120
120
|
### Bring your own component
|
|
121
121
|
|
|
@@ -180,11 +180,12 @@ For example, in a date picker UI, using the chain of responsibility pattern enab
|
|
|
180
180
|
The "which component to render" decision in the middleware enables 4 key customization techniques:
|
|
181
181
|
|
|
182
182
|
- Add a new component
|
|
183
|
-
- Register a new `<Audio>` middleware component to handle content type of
|
|
183
|
+
- Register a new `<Audio>` middleware component to handle content type of `audio/\*`
|
|
184
184
|
- Replace an existing component
|
|
185
|
-
- Register a new `<
|
|
185
|
+
- Register a new `<ImageV2>` middleware component to handle content type of `image/\*`
|
|
186
|
+
- The original `<Image>` will be replaced through starvation
|
|
186
187
|
- Remove an existing component
|
|
187
|
-
- Return `undefined` when handling content type of
|
|
188
|
+
- Return `undefined` when handling content type of `video/\*`
|
|
188
189
|
- Decorate an existing component
|
|
189
190
|
- Return a component which render `<div class="my-border"><Next /></div>`
|
|
190
191
|
|
|
@@ -194,15 +195,15 @@ After a bundle is lazy-loaded, register the component in the middleware.
|
|
|
194
195
|
|
|
195
196
|
When the chain of the `<Provider>` is updated, the lazy-loaded component will be rendered immediately.
|
|
196
197
|
|
|
197
|
-
This recipe can also
|
|
198
|
+
This recipe can also help creating bundles with multiple flavors.
|
|
198
199
|
|
|
199
200
|
## Advanced usage
|
|
200
201
|
|
|
201
|
-
### Registering component
|
|
202
|
+
### Registering component via functional programming
|
|
202
203
|
|
|
203
|
-
The `asMiddleware()` is a helper function to turn a React component into a
|
|
204
|
+
The `asMiddleware()` is a helper function to turn a React component into a middleware for simpler registration. As it operates in render-time, there are disadvantages. For example, a VDOM node is always required.
|
|
204
205
|
|
|
205
|
-
If precise rendering control is
|
|
206
|
+
If precise rendering control is required, consider registering the component natively using functional programming.
|
|
206
207
|
|
|
207
208
|
The following code snippet shows the conversion from the `<Image>` middleware component in our previous sample, into a component registered via functional programming.
|
|
208
209
|
|
|
@@ -345,13 +346,13 @@ function createChainOfResponsibility<Request = undefined, Props = { children?: n
|
|
|
345
346
|
|
|
346
347
|
### Return value
|
|
347
348
|
|
|
348
|
-
| Name | Description
|
|
349
|
-
| --------------------------- |
|
|
350
|
-
| `asMiddleware` | A helper function to convert a React component into a middleware.
|
|
351
|
-
| `Provider` | Entrypoint component, must wraps all usage of customizations
|
|
352
|
-
| `Proxy` | Proxy component, process the `request` from props and morph into the result component
|
|
353
|
-
| `types` | TypeScript: shorthand types, all objects are `undefined` intentionally
|
|
354
|
-
| `useBuildComponentCallback` | Callback hook which return a function to build the component for rendering the
|
|
349
|
+
| Name | Description |
|
|
350
|
+
| --------------------------- | -------------------------------------------------------------------------------------- |
|
|
351
|
+
| `asMiddleware` | A helper function to convert a React component into a middleware. |
|
|
352
|
+
| `Provider` | Entrypoint component, must wraps all usage of customizations |
|
|
353
|
+
| `Proxy` | Proxy component, process the `request` from props and morph into the result component |
|
|
354
|
+
| `types` | TypeScript: shorthand types, all objects are `undefined` intentionally |
|
|
355
|
+
| `useBuildComponentCallback` | Callback hook which return a function to build the component for rendering the request |
|
|
355
356
|
|
|
356
357
|
### Options
|
|
357
358
|
|
|
@@ -366,26 +367,26 @@ type Options = {
|
|
|
366
367
|
|
|
367
368
|
If `passModifiedRequest` is default or `false`, middleware will not be allowed to pass another reference of `request` object to their `next()` middleware. Instead, the `request` object passed to `next()` will be ignored and the next middleware always receive the original `request` object. This behavior is similar to [Express](https://expressjs.com/) middleware.
|
|
368
369
|
|
|
369
|
-
Setting to `true` will enable advanced scenarios and allow
|
|
370
|
+
Setting to `true` will enable advanced scenarios and allow one middleware to pass another instance of `request` object to influence their downstreamers.
|
|
370
371
|
|
|
371
|
-
When the option is default or `false
|
|
372
|
+
When the option is default or `false` but the `request` object is mutable, one middleware could still modify the `request` object and influence their downstreamers. It is recommended to follow immutable pattern when handling the `request` object, or use deep [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) to guarantee immutability.
|
|
372
373
|
|
|
373
374
|
### API of `asMiddleware`
|
|
374
375
|
|
|
376
|
+
`asMiddleware` wraps a React component into a middleware. Build will be done through additional `middleware` prop.
|
|
377
|
+
|
|
375
378
|
```ts
|
|
376
379
|
function asMiddleware(
|
|
377
380
|
middlewareComponent: ComponentType<MiddlewareComponentProps<Request, Props, Init>>
|
|
378
381
|
): ComponentMiddleware<Request, Props, Init>;
|
|
379
382
|
|
|
380
|
-
type MiddlewareProps<Request, Props, Init> = Readonly<{
|
|
381
|
-
init: Init;
|
|
382
|
-
Next: ComponentType<Partial<Props>>;
|
|
383
|
-
request: Request;
|
|
384
|
-
}>;
|
|
385
|
-
|
|
386
383
|
type MiddlewareComponentProps<Request, Props, Init> = Props &
|
|
387
384
|
Readonly<{
|
|
388
|
-
middleware:
|
|
385
|
+
middleware: Readonly<{
|
|
386
|
+
init: Init;
|
|
387
|
+
Next: ComponentType<Partial<Props>>;
|
|
388
|
+
request: Request;
|
|
389
|
+
}>
|
|
389
390
|
}>;
|
|
390
391
|
```
|
|
391
392
|
|
|
@@ -400,9 +401,9 @@ type UseBuildComponentCallback<Request, Props> = (
|
|
|
400
401
|
) => ComponentType<Props> | undefined;
|
|
401
402
|
```
|
|
402
403
|
|
|
403
|
-
For simplicity, instead of returning a component or `false`/`null`/`undefined`, the `useBuildComponentCallback` will only return a component or `undefined`.
|
|
404
|
+
For simplicity, instead of returning a React component or `false`/`null`/`undefined`, the `useBuildComponentCallback` will only return a React component or `undefined`.
|
|
404
405
|
|
|
405
|
-
The `fallbackComponent` is a component which all unhandled requests will sink into, including calls
|
|
406
|
+
The `fallbackComponent` is a component which all unhandled requests will sink into, including calls outside of `<Provider>`.
|
|
406
407
|
|
|
407
408
|
### API for Fluent UI
|
|
408
409
|
|
|
@@ -432,7 +433,7 @@ When rendering the element, `getKey` is called to compute the `key` attribute. T
|
|
|
432
433
|
|
|
433
434
|
## Designs
|
|
434
435
|
|
|
435
|
-
###
|
|
436
|
+
### How can I choose between request and props?
|
|
436
437
|
|
|
437
438
|
- Request is for *appearance*, while props is for *content*
|
|
438
439
|
- Request is for *deciding which component to render*, while props is for *what to render*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-chain-of-responsibility",
|
|
3
|
-
"version": "0.3.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Using chain of responsibility design pattern for compositing and customizing React component.",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/"
|
|
@@ -131,6 +131,6 @@
|
|
|
131
131
|
"react": ">=16.8.0"
|
|
132
132
|
},
|
|
133
133
|
"dependencies": {
|
|
134
|
-
"react-chain-of-responsibility": "^0.3.0
|
|
134
|
+
"react-chain-of-responsibility": "^0.3.0"
|
|
135
135
|
}
|
|
136
136
|
}
|