Notify User: Instead of canceling, a new fetch status called "delayed" is set if the request takes too long. This status is used to render a message to the user.
Add Cancel Button: A cancel button is added that allows the user to manually cancel the request if they wish.
Abort on Cancel: When the cancel button is clicked, the request is aborted using the AbortController.
import React, { useState, useRef } from 'react';
const App = () => {
const [fetchStatus, setFetchStatus] = useState('idle');
const controllerRef = useRef(null);
const fetchData = async () => {
setFetchStatus('loading');
controllerRef.current = new AbortController();
const { signal } = controllerRef.current;
setTimeout(() => {
if (fetchStatus === 'loading') {
setFetchStatus('delayed');
}
}, 2000);
try {
const res = await fetch('https://api.example.com/users', { signal });
const data = await res.json();
setFetchStatus('success');
// Do something with data
} catch (e) {
if (e.name === 'AbortError') {
setFetchStatus('canceled');
} else {
setFetchStatus('error');
}
}
};
const cancelRequest = () => {
controllerRef.current.abort();
};
return (
<div>
<button onClick={fetchData} disabled={fetchStatus === 'loading' || fetchStatus === 'delayed'}>
Load Users
</button>
{fetchStatus === 'delayed' && (
<div>
This response is taking longer than normal.
<button onClick={cancelRequest}>Cancel</button>
</div>
)}
{/* Render based on other fetchStatus values */}
</div>
);
};
export default App;