Appearance
useAsyncState
Reactive async state. It will not block your component and triggers changes once the promise is ready.
Demo
Usage
tsx
import { useAsyncState } from '@reause/core'
const initialState = { value: { id: null } }
const { state, isReady, isLoading, error, execute } = useAsyncState(
fetchTodo,
initialState,
)Return Values
| Property | Description |
|---|---|
state | The result of the async function |
setState | Set the state value directly, without re-executing the async function |
isReady | true when the latest execution has resolved successfully. Reset to false on each execution and stays false if it rejects |
isLoading | true while the promise is pending |
error | The error if the promise was rejected |
execute | Re-execute the async function with optional delay |
executeImmediate | Re-execute immediately (shorthand for execute(0)) |
Awaiting the Result
The return value is thenable, so you can await it and destructure directly:
tsx
const { state, isReady } = await useAsyncState(fetchData, null)
// `state` is now populated, `isReady` is trueManual Execution
Set immediate: false to prevent automatic execution on mount.
tsx
import { useAsyncState } from '@reause/core'
const { state, execute, executeImmediate } = useAsyncState(action, '', { immediate: false })
async function action() {
await new Promise(resolve => setTimeout(resolve, 500))
return 'done'
}
// trigger manually
executeImmediate()
execute(500) // delayed executionOptions
tsx
const { state } = useAsyncState(promise, initialState, {
// Execute immediately on mount (default: true)
immediate: true,
// Delay before first execution in ms (default: 0)
delay: 0,
// Reset state to initial before each execution (default: true)
resetOnExecute: true,
// Accepted for API parity; no-op in React (default: true)
shallow: true,
// Throw errors instead of catching them (default: false)
throwError: false,
// Called when promise resolves
onSuccess(data) {
console.log('Success:', data)
},
// Called when promise rejects
onError(error) {
console.error('Error:', error)
},
})shallow is a no-op
VueUse uses shallow to choose between shallowRef and ref for state (default true). React state is never deep-wrapped, so the option — and the Shallow generic that mirrors it — is accepted for API parity only and has no effect: state is always the plain resolved value.
Type Declarations
Toggle
ts
export interface UseAsyncStateReturnBase<Data, Params extends any[], _Shallow extends boolean> {
state: Data;
setState: Dispatch<SetStateAction<Data>>;
isReady: boolean;
isLoading: boolean;
error: unknown;
execute: (delay?: number, ...args: Params) => Promise<Data | undefined>;
executeImmediate: (...args: Params) => Promise<Data | undefined>;
}
export type UseAsyncStateReturn<Data, Params extends any[], Shallow extends boolean> = UseAsyncStateReturnBase<Data, Params, Shallow> & PromiseLike<UseAsyncStateReturnBase<Data, Params, Shallow>>
export interface UseAsyncStateOptions<Shallow extends boolean = true, D = any> {
delay?: number;
immediate?: boolean;
onError?: (e: unknown) => void;
onSuccess?: (data: D) => void;
resetOnExecute?: boolean;
shallow?: Shallow;
throwError?: boolean;
}
export function useAsyncState<Data, Params extends any[] = any[], Shallow extends boolean = true>(promise: Promise<Data> | ((...args: Params) => Promise<Data>), initialState: Data, options?: UseAsyncStateOptions<Shallow, Data>): UseAsyncStateReturn<Data, Params, Shallow>