PatternHookAPIAsync
Data Fetching Hook
A comprehensive data fetching hook with loading states, error handling, and automatic refetching capabilities.
Preview
User Data
Loading...
Code
import { useState, useEffect, useCallback } from 'react'
interface FetchState<T> {
data: T | null
loading: boolean
error: Error | null
}
interface FetchOptions {
enabled?: boolean
refetchInterval?: number
}
export function useFetch<T>(
url: string,
options: FetchOptions = {}
): FetchState<T> & { refetch: () => Promise<void> } {
const { enabled = true, refetchInterval } = options
const [state, setState] = useState<FetchState<T>>({
data: null,
loading: true,
error: null,
})
const fetchData = useCallback(async () => {
if (!enabled) return
setState((prev) => ({ ...prev, loading: true, error: null }))
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.json()
setState({ data, loading: false, error: null })
} catch (error) {
setState({
data: null,
loading: false,
error: error instanceof Error ? error : new Error('Unknown error'),
})
}
}, [url, enabled])
useEffect(() => {
fetchData()
}, [fetchData])
useEffect(() => {
if (!refetchInterval || !enabled) return
const interval = setInterval(fetchData, refetchInterval)
return () => clearInterval(interval)
}, [refetchInterval, enabled, fetchData])
return { ...state, refetch: fetchData }
}
// Usage example:
function UserList() {
const { data, loading, error, refetch } = useFetch<User[]>('/api/users')
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<div>
<button onClick={refetch}>Refresh</button>
{data?.map((user) => <div key={user.id}>{user.name}</div>)}
</div>
)
}Looking for more?
Browse the full collection of patterns or check out other exploration topics.