Reputation: 19
cancel
button. I want controller.abort() to trigger to cancel all API calls (let's call this method as *cancelAllCalls*()
)Problems : (1) I have to initiate controller.abort() outside useEffect. >> This required controller variable to be accessible inside *cancelAllCalls()*
- Not working
(2) If I try to do a setState
inside *cancelAllCalls()*
and add that as a dependency in the useEffect
to call controller.abort()
it will still re-initiate the controller and the signal passed to the APIs will also change - Not working
Note : I am able to achieve it by adding an eventListner on by cancel
button inside the useEffect only (& I made sure it happens only once by using a flag) and then calling controller .abort()
inside it. But I am not quite contented with this approach.
Any suggestions/guidance here?
Upvotes: 1
Views: 3355
Reputation: 1597
You can do something like this:
function TestComponent(props) {
const ref = React.useRef(null);
React.useEffect(() => {
ref.current= new AbortController;
return () => (ref.current.abort());
}, []);
const cancelAllCalls= ()=>{
ref.current.abort();
ref.current= new AbortController();
}
// your hooks
React.useEffect(() => {
//..
}, [myVar])
return ()
}
Or like this (Live Demo):
import React from "react";
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
// Note: the related network request will also be aborted
function TestComponent(props) {
const [cancel, done, result, err] = useAsyncEffect(
function* () {
return (yield cpAxios(props.url).timeout(props.timeout)).data;
},
{ states: true, deps: [props.url] }
);
return (
<div>
<div>
{done ? (err ? err.toString() : JSON.stringify(result)) : "loading..."}
</div>
<button onClick={cancel} disabled={done}>
Cancel async effect
</button>
</div>
);
}
Upvotes: 5