Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/closeio/use-abortable-effect
Super simple React hook for running abortable effects based on the AbortController API.
https://github.com/closeio/use-abortable-effect
Last synced: about 1 month ago
JSON representation
Super simple React hook for running abortable effects based on the AbortController API.
- Host: GitHub
- URL: https://github.com/closeio/use-abortable-effect
- Owner: closeio
- License: mit
- Created: 2020-06-18T08:22:57.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T09:17:09.000Z (almost 2 years ago)
- Last Synced: 2024-10-01T21:36:14.244Z (3 months ago)
- Language: JavaScript
- Homepage: https://closeio.github.io/use-abortable-effect/
- Size: 1.69 MB
- Stars: 12
- Watchers: 16
- Forks: 0
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# use-abortable-effect
[![NPM](https://img.shields.io/npm/v/@closeio/use-abortable-effect.svg)](https://www.npmjs.com/package/@closeio/use-abortable-effect) [![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-success)](https://prettier.io)
Super simple React hook for running abortable effects based on the [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) API.
[Check the live DEMO](https://closeio.github.io/use-abortable-effect/).
###
Interested in working on projects like this? [Close](https://close.com) is looking for [great engineers](https://jobs.close.com) to join our team!
## Install
```bash
yarn add @closeio/use-abortable-effect
```## Benefits
- Extremely lightweight (less than 500B minzipped).
- It uses the [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) API and it is compatible with the [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API.
- If a browser does not support the [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) API then the hook behaves exactly like a regular [`useEffect`](https://reactjs.org/docs/hooks-effect.html) hook. See [Can I Use](https://caniuse.com/#search=abortcontroller) for browser support overview.
- No other 3rd-party dependencies.## API differences over [`useEffect`](https://reactjs.org/docs/hooks-effect.html)
- API is compatible with [`useEffect`](https://reactjs.org/docs/hooks-effect.html),
where the effect function you pass-in accepts an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) instance as a param and you
can return a cleanup function that accepts an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) instance.
- Supports abortable [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests.
- Supports running custom operations/computations that can be easily aborted.
- Auto-aborts effects on re-run (or component unmount), unless you provide
a custom cleanup function.```jsx
useEffect(() => {
// do somethingreturn () => {
/* cleanup */
};
}, [deps]);const abortControllerRef = useAbortableEffect(
(abortSignal) => {
// do somethingreturn (abortController) => {
/* do cleanup, you should probably abort */
};
},
[deps],
);
```## Usage
### Abortable [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests
```jsx
import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';export default function MyAbortableFetchComponent() {
const abortControllerRef = useAbortableEffect((abortSignal) =>
fetch(url, { signal: abortSignal })
.then(/* … */)
.catch((rejection) => {
if (rejection.name !== 'AbortError') {
// Re-throw or handle non-abort rejection in another way.
return Promise.reject(rejection);
}
}),
);const handleManualAbort = () => abortControllerRef.current.abort();
// …
}
```### Arbitrary computation that can be aborted
```jsx
import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';export default function MyAbortableComputationComponent() {
const abortControllerRef = useAbortableEffect(abortSignal => {
new Promise((resolve, reject) => {
// Should be a DOMException per spec.
const abortRejection = new DOMException(
'Calculation aborted by the user',
'AbortError',
);// Handle when abort was requested before starting the computation.
if (abortSignal.aborted) {
return reject(abortRejection);
}// This simulates an expensive computation.
const timeout = setTimeout(() => resolve(1), 5000);// Listen for abort request.
abortSignal.addEventListener('abort', () => {
clearTimeout(timeout);
reject(abortRejection);
});
})
.then(/* … */)
.catch(rejection => {
if (rejection.name !== 'AbortError') {
// Re-throw or handle non-abort rejection in another way.
return Promise.reject(rejection);
}
}),
});const handleManualAbort = () => abortControllerRef.current.abort();
// …
}
```### Custom cleanup function
```jsx
import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';export default function MyCustomCleanupComponent() {
const [gotAborted, setGotAborted] = useState(false);const abortControllerRef = useAbortableEffect((abortSignal) => {
fetch(url, { signal: abortSignal })
.then(/* … */)
.catch((rejection) => {
if (rejection.name !== 'AbortError') {
// Re-throw or handle non-abort rejection in another way.
return Promise.reject(rejection);
}
});// Just return a function like in `useEffect`, with the difference that you
// get the abort controller (not a ref) as a param.
return (controller) => {
controller.abort();
setGotAborted(true);
};
});const handleManualAbort = () => abortControllerRef.current.abort();
// …
}
```## License
MIT © [Close](https://github.com/closeio)