@saborter/react
v2.0.0
Published
A library for canceling asynchronous requests with React integration
Maintainers
Readme

A library for canceling asynchronous requests that combines the Saborter library and React.
📚 Documentation
The documentation is divided into several sections:
📦 Installation
npm install @saborter/react
# or
yarn add @saborter/react📖 Possibilities
- The
aborterfield always has the same reference to theAborterinstance. - Automatically abort the request when the component is unmounted.
- Automatically unsubscribe from all listeners when the component is unmounted.
🚀 Quick Start
Basic Usage
import { useAborter } from '@saborter/react';
const Component = () => {
// Create an Aborter instance via the hook
const { aborter } = useAborter();
// Use for the request
const fetchData = async () => {
try {
const data = await aborter.try((signal) => fetch('/api/data', { signal }));
console.log('Data received:', data);
} catch (error) {
console.error('Request error:', error);
}
};
};🔧 API
useAborter
Props
const { aborter } = new useAborter(props?: UseAborterProps);Props Parameters
| Parameter | Type | Description | Required |
| --------- | ----------------- | ----------------------------- | -------- |
| props | UseAborterProps | Aborter configuration options | No |
UseAborterProps:
{
/**
Callback function for abort events.
Associated with EventListener.onabort.
It can be overridden via `aborter.listeners.onabort`
*/
onAbort?: OnAbortCallback;
/**
A function called when the request state changes.
It takes the new state as an argument.
Can be overridden via `aborter.listeners.state.onstatechange`
*/
onStateChange?: OnStateChangeCallback;
/**
A flag responsible for releasing resources.
This includes unsubscribing, clearing fields, and removing references to passed callback functions.
@default true
*/
dispose?: boolean;
}Properties
aborter: Aborter
Returns the Aborter instance.
const { aborter } = useAborter();
// Using signal in the request
fetch('/api/data', {
signal: aborter.signal
});requestState: RequestState
The current value of the request's state. May be undefined if the state has not yet been set.
The field is a react state associated with the aborter.listeners.state.value field.
const { requestState } = useAborter();
console.log(requestState); // 'cancelled' / 'pending' / 'fulfilled' / 'rejected' / 'aborted'useReusableAborter
Props
// The type can be found in `saborter/types`
const reusableAborter = new useReusableAborter(props?: ReusableAborterProps);Props Parameters
| Parameter | Type | Description | Required |
| --------- | ---------------------- | ------------------------------------- | -------- |
| props | ReusableAborterProps | ReusableAborter configuration options | No |
ReusableAborterProps:
{
/**
* Determines which listeners are carried over when the abort signal is reset.
* - If `true`, all listeners (both `onabort` and event listeners) are preserved.
* - If `false`, no listeners are preserved.
* - If an object, specific listener types can be enabled/disabled individually.
*/
attractListeners?: boolean | AttractListeners;
}Properties
signal: AbortSignal
Returns the AbortSignal associated with the current controller.
const reusableAborter = useReusableAborter();
// Using signal in the request
fetch('/api/data', {
signal: reusableAborter.signal
});Methods
abort(reason?): void
Parameters:
reason?: any- the reason for aborting the request.
Immediately cancels the currently executing request.
[!NOTE] Can be called multiple times. Each call will restore the
signal, and theabortedproperty will always befalse.
🎯 Usage Examples
Basic Usage
import { useState } from 'react';
import { AbortError } from 'saborter';
import { useAborter } from '@saborter/react';
const Component = () => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(false);
// Create an Aborter instance via the hook
const { aborter } = useAborter();
// Use for the request
const fetchData = async () => {
try {
setLoading(true);
const user = await aborter.try((signal) => fetch('/api/user', { signal }));
setUser(user);
} catch (error) {
if (error instanceof AbortError) {
// An abort error will occur either when the `aborter.abort()` method is called or when the component is unmounted.
console.error('Abort error:', error);
}
console.error('Request error:', error);
} finally {
setLoading(false);
}
};
return <h1>{loading ? 'Loading...' : user.fullname}</h1>;
};The AbortError initiator changed while unmounting the component
import { AbortError } from 'saborter';
import { useAborter } from '@saborter/react';
const Component = () => {
const { aborter } = useAborter();
const fetchData = async () => {
try {
const user = await aborter.try((signal) => fetch('/api/user', { signal }));
} catch (error) {
if (error instanceof AbortError) {
console.error('Abort error initiator:', error.initiator); // 'component-unmounted';
}
}
};
};Using useReusableAborter
const aborter = new useReusableAborter();
// Get the current signal
const signal = aborter.signal;
// Attach listeners
signal.addEventListener('abort', () => console.log('Listener 1'));
signal.addEventListener('abort', () => console.log('Listener 2'), { once: true }); // won't be recovered
// Set onabort handler
signal.onabort = () => console.log('Onabort handler');
// First abort
aborter.abort('First reason');
// Output:
// Listener 1
// Listener 2 (once)
// Onabort handler
// The signal is now a fresh one, but the non‑once listeners and onabort are reattached
signal.addEventListener('abort', () => console.log('Listener 3')); // new listener, will survive next abort
// Second abort
aborter.abort('Second reason');
// Output:
// Listener 1
// Onabort handler
// Listener 3📋 License
MIT License - see LICENSE for details.
