Provides a hook to provide state around an async function call
npm install use-async-call!npm


!NPM
Provides an abstraction over the lower-level use-async-reducer, handles calls to useEffect and handles cancelation when the inputs change or components unmounts to avoid modifying stale data
```
npm install use-async-call
`ts
import useAsyncCall from 'use-async-call'
const [state, {update, refresh, actions}] = useAsyncCall(
asyncCreator,
(options = {})
)
`

- asyncCreator An async method (returns a promise), create this method with useCallback if it depends on state from the component
`ts`
const [searchText, setSearchText] = useState('')
const fetchData = useCallback(() => Api.search(searchText), [searchText])
- options
`tsdata
interface UseAsyncCallOptions
/**
* Initial value used for of state
*/
initialValue?: T
/**
* When true, will not call actions.initalize when asyncCreator updates
* This keeps the data in the store between updates, useful when the identity
* of the data does not belong to the inputs, example would be a search
* component that uses "search text" as an input
*/
dontReinitialize?: boolean
/**
* Callback called after call is successful
* @param data Data returned from async caller
*/
onSuccess?(data?: T): void
/**
* Callback called after async call throws
* @param error Error thrown by async caller
*/
onFailure?(error?: Error): void
/**
* Callback always called after async call completes
*/
onComplete?(): void
}
`
- state an object containing state of async call
`ts`
const state: Loadable = {
data: {}, // any data
loading: false, // true when calls in progress
error: null // instance of Error if calls throw
}
- update(asyncUpdater, updateOptions = {}) method used to update the state
- asyncUpdater either a promise or a method which returns a promise, the result will be set to the data value of the stateupdateOptions
-
`tsupdate
interface UseAsyncCallUpdateOptions
/**
* Should thrown errors be re-thrown in the resulting promise from ;
* useful when using in conjuction with form libraries that expect errors
* when submitting form values
*/
throwError?: boolean
/**
* If the caller throws, sets state.error to the error and state.data tonull
*
*/
saveError?: boolean
/**
* Callback called after call is successful
* @param data Data returned from async caller
*/
onSuccess?(data?: T): void
/**
* Callback called after async call throws
* @param error Error thrown by async caller
*/
onFailure?(error?: Error): void
/**
* Callback always called after async call completes
*/
onComplete?(): void
}
`
- refresh method used to re-call the method passed to useAsyncCall
- actions action methods created by use-async-reducer
`tsloading
interface AsyncReducerBoundActions
/**
* To be called at the beginning of a request, sets to true`
*/
request(): void
/**
* To be called with the data to be saved into the state
* @param payload Result of the async call
*/
success(payload: T): void
/**
* To be called when the async call fails
* @param error
*/
failure(error: Error): void
/**
* Can be called when a call fails/complete and the result is being discarded
*/
complete(): void
}
`tsx
import React, {useCallback} from 'react'
import useAsyncCall from 'use-async-call'
import Api from './custom-api'
const DataLoadingComponent: React.FC<{id: number}> = ({id}) => {
const fetchData = useCallback(() => Api.fetchModelData(id), [id])
const [model] = useAsyncCall(fetchData)
// model is now managed, it will automatically fetch new data when id prop`
// changes and update the state to reflect any changes
}
`tsx
import React, {useCallback} from 'react'
import useAsyncCall from 'use-async-call'
import Api from './custom-api'
interface User {
id: number
name: string
}
const UserProfile: React.FC<{userId: number}> = ({userId}) => {
const [name, setName] = useState('')
const fetchUser = useCallback(() => Api.fetchUserById(userId), [userId])
const [user, {update: updateUser}] = useAsyncCall
const handleUpdateUserName = useCallback((): Promise
return Api.updateUser(userId, {name})
}, [userId, name])
return (
{user.data && (
<>
value={name}
onChange={(event) => setName(event.target.value)}
/>
disabled={user.loading}
onClick={() => updateUser(handleUpdateUserName)}
>
Update Name
>
)}
$3
`ts
import {useCallback} from 'react'
import useAsyncCall, {Loadable} from 'use-async-call'import Api from './custom-api'
interface User {
id: number
name: string
}
export function useUserData(
userId: number
): [Loadable, (userData: Partial) => Promise] {
const fetchUser = useCallback(() => Api.fetchUserById(userId), [userId])
const [user, {update: updateUser}] = useAsyncCall(fetchUser)
}, [])
const handleUpdateUser = useCallback(
(userData: Partial) => {
return updateUser(Api.updateUser(userId, userData), {
onSuccess() {
alert('Updated user!')
},
onFailure() {
alert('Failed to update user')
}
})
},
[userId]
)
return [user, handleUpdateUser]
}
`$3
`tsx
import React, {useCallback, useState} from 'react'
import useAsyncCall from 'use-async-call'import SearchApi from './search-api'
export function useSearchData(searchText: string) {
const fetchData = useCallback(() => SearchApi.find(searchText), [searchText])
return useAsyncCall(fetchData, {dontReinitialize: true})
}
const SearchComponent: React.FC = () => {
const [searchText, setSearchText] = useState('')
const [searchData] = useSearchData(searchText)
return (
<>
value={searchText}
onChange={(event) => {
setSearchText(event.target.value)
}}
/>
{searchData.data && (
<>
Search Results
{searchData.data.map((searchResult) => (
- {searchResult.name}
))}
>
)}
>
)
}
``