useAsyncState()
Live demo: useAsyncState
Async loadable state: loading / ready / error, optional data, and cancel for stale work.
Loading demo...
Demo sourceJSX
Overview
useAsyncState wraps an async producer function (() => Promise<T>) and exposes state, loading, error, and execute so you can load remote data (or any async work) with a predictable UI lifecycle. On execute, it clears the error, toggles loading, awaits the producer, then stores the resolved value or captures failures; with immediate: true it runs once on mount, and options like initialState and resetOnExecute let you seed the UI or reset before each run.
What it accepts
producer: () => Promise<T>.options: UseAsyncStateOptions<T> = {}.
What it returns
state: Latest resolved value (shape depends on generics / producer). TypeT | undefined.loading: Whether async work is in progress. Typeboolean.error: Last failure, or cleared when idle. Typeunknown.execute: Runs async work again and updates state. Type() => Promise<T>.
Usage
Copy-paste ready sample: import the hook and call it inside a component.
import useAsyncState from '@dedalik/use-react/useAsyncState'
function Example() {
const result = useAsyncState()
return (
<div>
<h3>useAsyncState state</h3>
<pre>{JSON.stringify(result, null, 2)}</pre>
</div>
)
}
export default function Demo() {
return <Example />
}API Reference
useAsyncState
Signature: useAsyncState(producer: () => Promise<T>, options: UseAsyncStateOptions<T> = {}): { state: T | undefined, loading: boolean, error: unknown, execute: () => Promise<T> }
Parameters
producer(() => Promise<T>) - Async function that loads data; called byexecute(and on mount whenimmediateistrue).options(optionalUseAsyncStateOptions<T>) -immediateruns on mount,initialStateseedsstate,resetOnExecuteresetsstatetoinitialStatebefore each run. Default:{}.
Returns
Object with:
state- Latest resolved value (shape depends on generics / producer). (T | undefined).loading- Whether async work is in progress. (boolean).error- Last failure, or cleared when idle. (unknown).execute- Runs async work again and updates state. (() => Promise<T>).
Copy-paste hook
import { useEffect, useState } from 'react'
export interface UseAsyncStateOptions<T> {
immediate?: boolean
resetOnExecute?: boolean
initialState?: T
}
/**
* Resolves async producer into managed loading/data/error state.
*/
export default function useAsyncState<T>(
producer: () => Promise<T>,
options: UseAsyncStateOptions<T> = {},
): {
state: T | undefined
loading: boolean
error: unknown
execute: () => Promise<T>
} {
const { immediate = true, resetOnExecute = false, initialState } = options
const [state, setState] = useState<T | undefined>(initialState)
const [loading, setLoading] = useState(immediate)
const [error, setError] = useState<unknown>(undefined)
const execute = async () => {
if (resetOnExecute) setState(initialState)
setLoading(true)
setError(undefined)
try {
const result = await producer()
setState(result)
return result
} catch (err) {
setError(err)
throw err
} finally {
setLoading(false)
}
}
useEffect(() => {
if (immediate) void execute()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [immediate])
return { state, loading, error, execute }
}import { useEffect, useState } from 'react'
export default function useAsyncState(producer, options = {}) {
const { immediate = true, resetOnExecute = false, initialState } = options
const [state, setState] = useState(initialState)
const [loading, setLoading] = useState(immediate)
const [error, setError] = useState(undefined)
const execute = async () => {
if (resetOnExecute) setState(initialState)
setLoading(true)
setError(undefined)
try {
const result = await producer()
setState(result)
return result
} catch (err) {
setError(err)
throw err
} finally {
setLoading(false)
}
}
useEffect(() => {
if (immediate) void execute()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [immediate])
return { state, loading, error, execute }
}