You can use the typical approach with isMounted/isUnmounted flag variable to avoid changing its state after the component has been unmounted. Something like the following:
function Component() {
const isUnmounted = React.useRef(false);
const [error, setError] = React.useState("");
React.useEffect(() => () => (isUnmounted.current = true), []);
return <form onSubmit={(e)=>{
e.preventDefault();
sendRegistrationCode('email').then((result) => {
if (result.data.message) {
!isUnmounted.current && setError({
type: result.data.message.type,
message: result.data.message.message,
});
}
});
}}></form>;
}
Of course, this old well-known trick actually doesn't cancel async routines or unsubscribe from anything, it just ignores their results.
And just for reference, as an experimental approach, you can do the following trick with a custom callback hook. It provides a wrapper around cancelable promises. Note: Unmounting the component while fetching will automatically cause aborting of the network request. (minimal live demo)
import React, { useState } from "react";
import { useAsyncCallback, E_REASON_UNMOUNTED } from "use-async-effect2";
import { CanceledError } from "c-promise2";
import cpAxios from "cp-axios";
export default function TestComponent(props) {
const [text, setText] = useState("");
const [error, setError] = useState("");
const sendRegistrationCode = (email) => {
return cpAxios(props.url);
};
const submit = useAsyncCallback(
function* (e) {
e.preventDefault();
try {
const response = yield sendRegistrationCode("email").timeout(
props.timeout
);
if (response.data.message) {
setError({
type: response.data.message.type,
message: response.data.message.message
});
return;
}
setText(response); //response OK
} catch (err) {
CanceledError.rethrow(err, E_REASON_UNMOUNTED);
setError({ type: "fetch", message: err.message });
}
},
{ cancelPrevious: true }
);
return (
<div className="component">
<div className="caption">useAsyncEffect demo:</div>
<div>
{error ? (
<span style={{ color: "red" }}>{JSON.stringify(error)}</span>
) : (
<span>{JSON.stringify(text)}</span>
)}
</div>
<form action={props.url} onSubmit={submit}>
<input type="submit" value="Send form" />
</form>
</div>
);
}