@@ -14,7 +14,7 @@ This is an no-op, but it indicates a memory leak in your application.
14
14
To fix, cancel all subscriptions and asynchronous task in "a useEffect cleanup function".
15
15
````
16
16
It uses [ c-promise2] ( https://www.npmjs.com/package/c-promise2 ) to make it work.
17
- When it used in conjunction with other libraries that work with the CPromise,
17
+ When it used in conjunction with other libraries from CPromise ecosystem ,
18
18
such as [ cp-fetch] ( https://www.npmjs.com/package/cp-fetch ) and [ cp-axios] ( https://www.npmjs.com/package/cp-axios ) ,
19
19
you get a powerful tool for building asynchronous logic for your React components.
20
20
You just have to use ` generators ` instead of an async function to make your code cancellable,
@@ -52,70 +52,92 @@ function JSONViewer(props) {
52
52
````
53
53
Example with a timeout & error handling ([ Live demo] ( https://codesandbox.io/s/async-effect-demo1-vho29?file=/src/TestComponent.js ) ):
54
54
```` jsx
55
- import React from " react" ;
56
- import {useState } from " react" ;
57
- import {useAsyncEffect , E_REASON_UNMOUNTED } from " use-async-effect2" ;
58
- import {CanceledError } from " c-promise2" ;
55
+ import React , { useState } from " react" ;
56
+ import { useAsyncEffect , E_REASON_UNMOUNTED } from " use-async-effect2" ;
57
+ import { CanceledError } from " c-promise2" ;
59
58
import cpFetch from " cp-fetch" ;
60
59
61
60
export default function TestComponent (props ) {
62
- const [text , setText ] = useState (" " );
63
-
64
- const [cancel ]= useAsyncEffect (function * ({onCancel}) {
65
- console .log (" mount" );
66
-
67
- this .timeout (5000 );
68
-
69
- onCancel (()=> console .log (' scope canceled' ));
70
-
71
- try {
72
- setText (" fetching..." );
73
- const response = yield cpFetch (props .url );
74
- const json = yield response .json ();
75
- setText (` Success: ${ JSON .stringify (json)} ` );
76
- } catch (err) {
77
- CanceledError .rethrow (err, E_REASON_UNMOUNTED ); // passthrough
78
- setText (` Failed: ${ err} ` );
79
- }
80
-
81
- return () => {
82
- console .log (" unmount" , this .isCanceled );
83
- };
84
- }, [props .url ]);
85
-
86
- // setTimeout(()=> cancel("Ooops!"), 1000);
87
-
88
- return < div> {text}< / div> ;
61
+ const [text , setText ] = useState (" " );
62
+
63
+ const cancel = useAsyncEffect (function * ({ onCancel }) {
64
+ console .log (" mount" );
65
+
66
+ this .timeout (props .timeout );
67
+
68
+ onCancel (() => console .log (" scope canceled" ));
69
+
70
+ try {
71
+ setText (" fetching..." );
72
+ const response = yield cpFetch (props .url );
73
+ const json = yield response .json ();
74
+ setText (` Success: ${ JSON .stringify (json)} ` );
75
+ } catch (err) {
76
+ CanceledError .rethrow (err, E_REASON_UNMOUNTED ); // passthrough
77
+ setText (` Failed: ${ err} ` );
78
+ }
79
+
80
+ return () => {
81
+ console .log (" unmount" );
82
+ };
83
+ },
84
+ [props .url ]
85
+ );
86
+
87
+ return (
88
+ < div className= " component" >
89
+ < div className= " caption" > useAsyncEffect demo: < / div>
90
+ < div> {text}< / div>
91
+ < button onClick= {cancel}> Abort< / button>
92
+ < / div>
93
+ );
89
94
}
90
95
````
91
96
useAsyncCallback example ([ Live demo] ( https://codesandbox.io/s/use-async-callback-bzpek?file=/src/TestComponent.js ) ):
92
97
```` javascript
93
98
import React from " react" ;
94
- import {useState } from " react" ;
95
- import {useAsyncCallback } from " use-async-effect2 " ;
96
- import {CPromise } from " c-promise2" ;
99
+ import { useState } from " react" ;
100
+ import { useAsyncCallback , E_REASON_UNMOUNTED } from " ../../lib/ use-async-effect " ;
101
+ import { CPromise , CanceledError } from " c-promise2" ;
97
102
98
- export default function TestComponent ( props ) {
103
+ export default function TestComponent2 ( ) {
99
104
const [text , setText ] = useState (" " );
100
105
101
- const asyncRoutine = useAsyncCallback (function * (v ){
102
- setText (` Stage1` );
103
- yield CPromise .delay (1000 );
104
- setText (` Stage2` );
105
- yield CPromise .delay (1000 );
106
- setText (` Stage3` );
107
- yield CPromise .delay (1000 );
108
- setText (` Done` );
109
- return v;
110
- })
111
-
112
- const onClick = ()=> {
113
- asyncRoutine (123 ).then (value => {
114
- console .log (` Result: ${ value} ` )
115
- }, console .warn );
116
- }
117
-
118
- return < div>< button onClick= {onClick}> Run async job< / button>< div> {text}< / div>< / div> ;
106
+ const asyncRoutine = useAsyncCallback (
107
+ function * (a , b ) {
108
+ setText (` Stage1` );
109
+ yield CPromise .delay (1000 );
110
+ setText (` Stage2` );
111
+ yield CPromise .delay (1000 );
112
+ setText (` Stage3` );
113
+ yield CPromise .delay (1000 );
114
+ setText (` Done` );
115
+ return Math .random ();
116
+ },
117
+ { cancelPrevious: true }
118
+ );
119
+
120
+ const onClick = () => {
121
+ asyncRoutine (123 , 456 ).then (
122
+ (value ) => {
123
+ setText (` Result: ${ value} ` );
124
+ },
125
+ (err ) => {
126
+ console .warn (err);
127
+ CanceledError .rethrow (E_REASON_UNMOUNTED );
128
+ setText (` Fail: ${ err} ` );
129
+ }
130
+ );
131
+ };
132
+
133
+ return (
134
+ < div className= " component" >
135
+ < div className= " caption" > useAsyncCallback demo: < / div>
136
+ < button onClick= {onClick}> Run async job< / button>
137
+ < div> {text}< / div>
138
+ < button onClick= {() => asyncRoutine .cancel ()}> Abort< / button>
139
+ < / div>
140
+ );
119
141
}
120
142
````
121
143
@@ -128,7 +150,7 @@ just use the codesandbox [demo](https://codesandbox.io/s/async-effect-demo1-vho2
128
150
129
151
## API
130
152
131
- ### useAsyncEffect(generatorFn, deps?): (function cancel(): boolean )
153
+ ### useAsyncEffect(generatorFn, deps?): (cancel(): boolean )
132
154
A React hook based on [ ` useEffect ` ] ( https://reactjs.org/docs/hooks-effect.html ) , that resolves passed generator as asynchronous function.
133
155
The asynchronous generator sequence and its promise of the result will be canceled if
134
156
the effect cleanup process is started before it completes.
@@ -141,11 +163,12 @@ The last argument passed to this function and `this` refer to the CPromise insta
141
163
### useAsyncCallback(generatorFn, options?: object): CPromiseAsyncFunction
142
164
This hook makes an async callback that can be automatically canceled on unmount or by user request.
143
165
#### options:
144
- - ` deps: any[] `
145
- - ` combine:boolean ` - allow only single thread running.
146
- All subsequent callings will return promises that subscribed to the pending promise of the first call.
166
+ - ` deps: any[] ` - effect dependencies
167
+ - ` combine:boolean ` - subscribe to the result of the async function already
168
+ running with the same arguments or run a new one.
147
169
- ` cancelPrevious:boolean ` - cancel the previous pending async function before running a new one.
148
- - ` concurrency: number=0 ` - set concurrency limit for simultaneous calls.
170
+ - ` concurrency: number=0 ` - set concurrency limit for simultaneous calls. ` 0 ` mean unlimited.
171
+ - ` queueSize: number=0 ` - set max queue size.
149
172
150
173
## Related projects
151
174
- [ c-promise2] ( https://www.npmjs.com/package/c-promise2 ) - promise with cancellation, decorators, timeouts, progress capturing, pause and user signals support
0 commit comments