I have a page with a Button A. When clicked, it makes an API call, and if successful, opens a new page. While the API call is being made, a modal appears to inform the user that a request is ongoing.
The modal contains a cancel button. If clicked, the new page should not open, and the state should reset so the user can cancel again if needed.
I use the useEffect hook to detect if the cancel button is clicked. If it is, the new page will not open. For the api call, I used await instead of settimeout(..)
I need to reset the variables in useEffect after the new page is either opened or not. I haven’t found a solution that handles the asynchronous nature of JavaScript. It’s essential to ensure that every time the cancel button is clicked, the user can click Button A and cancel the action repeatedly.
import React, { useState, useRef, useEffect } from 'react';
export default function NewApp(props) {
const [isModalOpen, setIsModalOpen] = useState(false);
const [apiRequestSuccessful, setApiRequestSuccessful] = useState(false);
const [isCancelClicked, setIsCancelClicked] = useState(false);
const handleButtonClick = async () => {
// Open the modal
setIsModalOpen(true);
setIsCancelClicked(false);
try {
// Make the API request
setTimeout(()=>{
console.log("making api call")
},3000)
setApiRequestSuccessful(true);
} catch (error) {
console.error('API request failed', error);
}
};
const handleCancelClick = () => {
setIsCancelClicked(true);
setIsModalOpen(false);
};
useEffect(() => {
// Check if the API request was successful and the cancel button wasn't clicked
if (apiRequestSuccessful && !isCancelClicked) {
window.open('https://example.com', '_blank');
// console.log("open new window")
}
setIsModalOpen(false)
}, [apiRequestSuccessful, isCancelClicked]);
return (
<div>
<button onClick={handleButtonClick}>Button A</button>
{isModalOpen && (
<Modal onCancel={handleCancelClick} />
)}
</div>
);
};
const Modal = ({ onCancel }) => {
return (
<div className="modal">
<p>Api call is being made...</p>
<button onClick={onCancel}>Cancel</button>
</div>
);
};
2
Answers
Why not store the fetch object in the state and once the
cancel
button is clicked you can cancel the fetch request? In theeffect
you can monitor the state of your fetch, if the fetch is canceled it will not open the new page but if it’s successful it will close the modal and present the new page. By that, there is no need to disable thecancel
button; all states will be connected to yourAPI request
status.But if you insist on using state, can you explain when the state needs to be reseated and what state needs to be rested?
Cancelling promises is difficult, you can store the request state in a state variable but you also have to store the request number or ID so that only the last request will count to go to the next page.
In this simplified example, the page only changes if the request is the latest request made, you can apply the same logic and if the request fails and is the latest request show an error message on the modal (if its open) etc.