I'm pretty new to React Hooks and I need some guidance with the following issue.
I'm submitting a form asynchronously. I do use a Promise that can be canceled for that.
Now, imagine that something happens until the promise resolves and the Component gets unmounted. When the promise resolves I get an error:
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
Basically I must cancel the Promise if the component gets unmounted. The return function of the useEffect
would be exactly what I need, but the problem is that I cannot start the Promise request inside useEffect
function since the request must be performed when the submit button is pressed and not when the component is mounted or updated.
How can the Promise be canceled when the component unmounts?
Note: I'm looking for a solution that doesn't involve isMounted
that has been declared an anti-pattern according to [react doc] [react doc]: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
Minimal Code Example:
const AccountDetails = ({ props }) => {
/* functions and variable declarations go here */
const [accountDetails, setAccountDetails] = useState({}); //initialize state variables
const handleSubmit = () => {
const data = { /* computed data */ };
dataService.get(
submitUrl,
data,
).then(
result => {
setAccountDetails(result); //here is where the error is thrown when the component is unmounted
}
);
};
return (
<div>
<!-- form fields -->
<button onClick={handleSubmit} .../>
</div>
);
};
I've tried the following solution, that oddly enough doesn't work .
const AccountDetails = ({ props }) => {
/* functions and variable declarations go here */
const [accountDetails, setAccountDetails] = useState({}); //initialize state variables
let submitAccountDetailsPromise = null;
useEffect(() => {
return () => {
/*DON'T UNDERSTAND HOW COME submitAccountDetailsPromise == NULL WHEN this code is executed after the submit button was pressed. */
submitAccountDetailsPromise && submitAccountDetailsPromise.cancel();
};
}, []);
const handleSubmit = () => {
const data = { /* computed data */ };
submitAccountDetailsPromise = dataService.get(
submitUrl,
data,
).then(
result => {
setAccountDetails(result); //here is where the error is thrown when the component is unmounted
}
);
};
return (
<div>
<!-- form fields -->
<button onClick={handleSubmit} .../>
</div>
);
};