Lightweight, feature-rich React hooks library for API data fetching and mutations with built-in retry logic, polling, and window focus refetching.
Install package using npm manager.
npm install react-fetch-pilotBuilt to streamline async state and network lifecycle handling
Simple API
Auto Retry
Polling Support
Focus Refetch
Abort Support
Zero Dependencies
TypeScript Ready
Safe Unmounting
import { useDataFetcher } from 'react-fetch-pilot'
function UserList() {
const { data, error, loading, refetch } = useDataFetcher(
[],
async (signal) => {
const res = await fetch('/api/users', { signal })
return { data: await res.json() }
},
{
enabled: true,
refetchInterval: 5000,
refetchOnWindowFocus: true,
retry: 3,
retryDelay: 1000,
}
)
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<div>
{data?.map(u => <div key={u.id}>{u.name}</div>)}
<button onClick={refetch}>Refresh</button>
</div>
)
}import { useMutation } from 'react-fetch-pilot'
function CreateUser() {
const { execute, data, error, loading } = useMutation(
async (userData) => {
const res = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(userData),
headers: { 'Content-Type': 'application/json' }
})
return { data: await res.json() }
},
{
onSuccess: (data) => console.log('Created:', data),
onError: (error) => console.error('Failed:', error)
}
)
const handleSubmit = async (e) => {
e.preventDefault()
await execute({ name: 'John Doe', email: 'john@example.com' })
}
return (
<form onSubmit={handleSubmit}>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create User'}
</button>
</form>
)
}Signature and options for useDataFetcher and useMutation
useDataFetcher<TData, TError>(
dependencies: DependencyList,
apiFunction: (signal: AbortSignal) => Promise<{ data: TData }>,
options?: UseDataFetcherOptions
): UseDataFetcherResult| Option | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Enable/disable automatic fetching |
| refetchInterval | number | undefined | Polling interval in milliseconds |
| refetchOnWindowFocus | boolean | false | Refetch when window regains focus |
| retry | number | 0 | Number of retry attempts on failure |
| retryDelay | number | 1000 | Base delay between retries (ms) |
| onSuccess | (data) => void | - | Callback on successful fetch |
| onError | (error) => void | - | Callback on fetch error |
useMutation<TData, TArgs, TError>(
apiFunction: (...args: TArgs) => Promise<{ data: TData }>,
options?: UseMutationOptions
): UseMutationResultReturns: { execute, data, error, loading }
const [userId, setUserId] = useState(1)
const { data, loading } = useDataFetcher(
[userId],
async (signal) => {
const res = await fetch(`/api/users/${userId}`, { signal })
return { data: await res.json() }
}
)const { data, loading, refetch } = useDataFetcher(
[],
fetchUsers,
{ enabled: false }
)
// Trigger manually:
// <button onClick={refetch}>Load Users</button>const { data, error, loading } = useDataFetcher(
[],
fetchCriticalData,
{
retry: 5,
retryDelay: 2000,
onError: (err) => console.error('Failed after retries:', err),
}
)interface User { id: number; name: string }
const { data } = useDataFetcher<User>(
[],
async (signal) => {
const res = await fetch('/api/user', { signal })
return { data: await res.json() }
}
)Released under the MIT License. Free for personal and commercial projects.