useAbortController
A custom hook for managing operations with an AbortController instance.
Add hook
Create a file use-abort-controller.ts
and copy & paste the code from useAbortController.
Hook
import { useRef, useState } from 'react'
export const useAbortController = (controller: AbortController) => {
if (!controller) {
throw new Error('AbortController instance is required. Make sure to provide a valid AbortController.')
}
const [isAborted, setIsAborted] = useState(false)
const controllerRef = useRef(controller)
const getSignal = () => {
return controllerRef.current.signal
}
const abort = () => {
controllerRef.current.abort()
setIsAborted(true)
}
const abortAfter = (time: number) => {
setTimeout(() => {
abort()
}, time)
}
const abortIf = (fn: (arg?: unknown) => unknown) => {
if (fn()) {
abort()
}
}
const abortIfAfter = (fn: (arg?: unknown) => unknown, time: number) => {
if (fn()) {
abortAfter(time)
}
}
return {
getSignal,
abort,
abortAfter,
abortIf,
abortIfAfter,
isAborted,
}
}
Usage
import { useEffect, useState } from 'react'
import { useAbortController } from './hooks/use-abort-controller'
const App = () => {
const abortController = new AbortController()
const [product, setProduct] = useState<any | null>(null)
const { abort, isAborted, getSignal } = useAbortController(abortController)
const signal = getSignal()
const fetchData = async () => {
try {
const response = await fetch('https://fakestoreapi.com/products/1', { signal })
const data = await response.json()
setProduct(data)
} catch (error) {
if (error instanceof Error) {
if (error.name === 'AbortError') {
console.log('Fetch aborted')
} else {
console.error('Error fetching data:', error)
}
}
} finally {
console.log(signal.aborted)
}
}
useEffect(() => {
fetchData()
}, [signal])
const handleAbortClick = () => {
abort()
}
const abortStatus = isAborted ? 'You canceled your request' : 'We are processing your request ...'
const requestStatus = product ? product.title : abortStatus
return (
<div
style={{
display:"flex",
flexDirection:"column",
alignItems:"center",
position: 'absolute',
top: '20%',
left: '45%',
width: 'auto',
}}
>
<p>{requestStatus}</p>
{product || isAborted ? null : (
<button onClick={handleAbortClick} style={{ marginTop: 20 }}>
Cancel
</button>
)}
</div>
)
}
export default App
API
Parameters
Name | Type | Description |
---|---|---|
controller | AbortController | The AbortController instance to manage operations. |
Returns
Name | Description |
---|---|
getSignal(): AbortSignal | Retrieves the AbortSignal associated with the provided controller. |
abort(): void | Aborts the associated operation. |
abortAfter(time: number): void | Aborts the associated operation after a specified delay. |
abortIf(fn: (arg?: unknown) => unknown): void | Aborts the operation if the provided condition is met. |
abortIfAfter(fn: (arg?: unknown) => unknown, time: number): void | Aborts the operation if the provided condition is met after a specified delay. |
isAborted: boolean | A boolean state indicating whether the operation has been aborted. |