Reputation: 8580
This is in a functional component.
I have a submit()
function that looks like so:
async function handleSubmit(event) {
event.preventDefault();
try {
let resp = await fetch("FOOBAR/BAX", {
method: 'POST',
body: JSON.stringify({ /*stuff*/})
});
if (resp.ok){
// yadda yadda yadda
props.history.push("/"); // navigate
}
}
}
Now, when I cause navigation to occur I'm getting the dreaded 'Can't perform a React state update on an unmounted component.' error.
So, using effects, how do I make sure this fetch call is cleaned up? All the examples I'm seeing use useEffect
to both set up and then cleanup the call (with cleanup function).
Upvotes: 0
Views: 508
Reputation: 203512
Clean up a fetch request by cancelling on dismount using an abort controller
Factor the fetch request logic out of the handler into the effect hook and use a state hook to trigger the effect to fire. Return the controller's abort
function in the effect hook to be called when the component unmounts.
const [body, setBody] = useState('');
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
if (body) {
fetch("FOOBAR/BAX", {
method: 'POST',
body: JSON.stringify(body),
signal, // add signal to request
})
.then(res => {
setBody(''); // clear request body value
if (res.ok) props.history.push('/');
});
}
return controller.abort; // return the abort function to be called when component unmounts
}, [body]);
const handleSubmit = (event) => {
event.preventDefault();
setBody({ /*stuff*/ }); // set request body value to trigger effect to fetch
};
Here's a codesandbox with this implemented as a react hook, with manual abort and automatic abort on unmounting.
Upvotes: 1