use-async-call
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
Install
npm install use-async-call
Usage
import useAsyncCall from ' use-async-call '
const [ state , { update , refresh , actions } ] = useAsyncCall (
asyncCreator ,
( options = { } )
)
Demo
Params
asyncCreator
An async method (returns a promise), create this method with useCallback
if it depends on state from the component
const [ searchText , setSearchText ] = useState ( ' ' )
const fetchData = useCallback ( ( ) => Api . search ( searchText ) , [ searchText ] )
interface UseAsyncCallOptions < T > {
initialValue ? : T
dontReinitialize ? : boolean
onSuccess ? ( data ? : T ) : void
onFailure ? ( error ? : Error ) : void
onComplete ? ( ) : void
}
Return values
state
an object containing state of async call
const state : Loadable = {
data : { } ,
loading : false ,
error : null
}
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 state
updateOptions
interface UseAsyncCallUpdateOptions < T > {
throwError ? : boolean
saveError ? : boolean
onSuccess ? ( data ? : T ) : void
onFailure ? ( error ? : Error ) : void
onComplete ? ( ) : void
}
refresh
method used to re-call the method passed to useAsyncCall
actions
action methods created by use-async-reducer
interface AsyncReducerBoundActions < T = any > {
request ( ) : void
success ( payload : T ) : void
failure ( error : Error ) : void
complete ( ) : void
}
Examples
Basic Example
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 )
}
A component which updates a value at an API
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 < User > ( fetchUser )
const handleUpdateUserName = useCallback ( ( ) : Promise < User > => {
return Api . updateUser ( userId , { name } )
} , [ userId , name ] )
return (
< div >
< h1 > User: { userId } </ h1 >
{ user . loading && < div > Loading... </ div > }
{ user . data && < div > { user . data . name } </ div > }
{ user . error && < div > { user . error . message } </ div > }
{ user . data && (
<>
< input
value = { name }
onChange = { ( event ) => setName ( event . target . value ) }
/>
< button
disabled = { user . loading }
onClick = { ( ) => updateUser ( handleUpdateUserName ) }
>
Update Name
</ button >
< / >
) }
</ div >
)
}
Create a custom hook to load and update a model
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 < User > , ( userData : Partial < User > ) => Promise < User > ] {
const fetchUser = useCallback ( ( ) => Api . fetchUserById ( userId ) , [ userId ] )
const [ user , { update : updateUser } ] = useAsyncCall < User > ( fetchUser )
} , [ ] )
const handleUpdateUser = useCallback (
( userData : Partial < User > ) => {
return updateUser ( Api . updateUser ( userId , userData ) , {
onSuccess ( ) {
alert ( ' Updated user! ' )
} ,
onFailure ( ) {
alert ( ' Failed to update user ' )
}
} )
} ,
[ userId ]
)
return [ user , handleUpdateUser ]
}
Get Data from a Search API
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 (
<>
< input
value = { searchText }
onChange = { ( event ) => {
setSearchText ( event . target . value )
} }
/>
{ searchData.data && (
<>
< h1 > Search Results </ h1 >
< ul >
{ searchData . data . map (( searchResult ) = > (
< li key = { searchResult . id } > { searchResult . name } </ li >
) ) }
</ ul >
</>
) }
< / >
)
}