AsyncFetcher it is a simple and useful React (web or native) component for asynchronous loading/fetch online data with help of axios.
Since the library is a JS-based solution, to install the latest version of react-async-fetcher
you only need to run:
$ npm install --save react-async-fetcher
or
$ yarn add react-async-fetcher
The AsyncFetcher component is based in function as child render to enhance your render with useful callback functions and props.
import React from "react";
import AsyncFetcher from "react-async-fetcher";
const MyIpWidget = () => (
<AsyncFetcher url="https://ipapi.co/json/">
{({ isLoading, error, data }) => {
// some loading state...
if (isLoading) {
return <p>Loading data...</p>;
}
// if has any error in your request
if (error) {
return (
<p>
<strong>Error:</strong> {error}
</p>
);
}
// if reach here your request was successful
return (
<p>
<strong>My IP:</strong> {data.ip} <br />
<strong>Location:</strong> {data.city} / {data.region}
</p>
);
}}
</AsyncFetcher>
);
import React from "react";
import AsyncFetcher from "react-async-fetcher";
const MyUser = () => (
// passing `params` as prop or component state you will generate some "/users?id=1" request
<AsyncFetcher autoFetch={false} method="get" url="https://jsonplaceholder.typicode.com/users" params={{ id: "1" }}>
{({ fetch, isLoading, error, data }) => {
// some loading state...
if (isLoading) {
return <p>Loading data...</p>;
}
// if has any error in your request
if (error) {
return (
<p>
<strong>Error:</strong> {error}
</p>
);
}
if (data) {
// if reach here your request was successful
return (
<p>
<strong>Name:</strong> {data.name}
</p>
);
}
// using the `fetch` prop/callback to call for JSON API
return (
<button onClick={fetch} type="button">
Find my user
</button>
);
}}
</AsyncFetcher>
);
import React from "react";
import AsyncFetcher from "react-async-fetcher";
const MyAutoComplete = () => (
<AsyncFetcher
debounce={300} // debounce/delay consecutive types for a good autocomplete requests performance
params={{ q: "" }} // initial data for controlled q input
canFetch={({ params }) => !!params.q} // allow new requests only if user has typed some username
url="https://api.github.com/search/users">
{({ isLoading, error, data, params, set, fetch }) => {
const hasQueryParam = !!params.q;
const hasData = hasQueryParam && data !== null && !!data.items;
const hasError = hasQueryParam && !!error;
return (
<form onSubmit={fetch}>
{hasError && (
<div className="alert alert-danger" role="alert">
<strong>Error:</strong> {JSON.stringify(error)}
</div>
)}
<div className="form-group">
<input
placeholder="Search for github username"
value={params.q}
onChange={event => set({ params: { q: event.target.value } })}
className="form-control"
/>
</div>
{hasQueryParam && isLoading && <p className="loading">Loading data...</p>}
{hasData && (
<div className="results">
{data.items.slice(0, 5).map(user => (
<span key={user.id} className="label label-default">
{user.login}
</span>
))}
</div>
)}
</form>
);
}}
</AsyncFetcher>
);
import React from "react";
import AsyncFetcher from "react-async-fetcher";
const SimplePost = () => (
<AsyncFetcher
method="post"
contentType="json"
url="https://jsonplaceholder.typicode.com/posts"
canFetch={({ postData }) => !!postData.title} // a litle validation for prevent empty post titles
postData={{ userId: "1", title: "", body: "" }} // initial data for controlled inputs
autoFetch={false}>
{({ isLoading, error, data, postData, set, fetch }) => (
<form method="post" onSubmit={fetch}>
{!!error && (
<div className="alert alert-danger" role="alert">
<strong>Error:</strong> {JSON.stringify(error)}
</div>
)}
{isLoading && <p className="loading">Loading data...</p>}
<div className="form-group">
<input
placeholder="Insert your post title (required)"
value={postData.title}
onChange={event => set({ postData: { title: event.target.value } })}
className="form-control"
required
/>
</div>
<div className="form-group">
<textarea
placeholder="Insert your post body"
value={postData.body}
onChange={event => set({ postData: { body: event.target.value } })}
className="form-control"
rows={3}
/>
</div>
<button disabled={isLoading} type="submit" className="btn btn-primary">
Send my post
</button>
{!!data && (
<p>
<strong>Results:</strong> {JSON.stringify(data)}
</p>
)}
</form>
)}
</AsyncFetcher>
);
For more info and good examples (including Form Upload and usage with Formik) visit the website project.
This is the list of main props that all render functions receive in a first and only object props that you should probably know about.
function(customRequest:object)
| defaults tonull
When you call this function you manually ask for a new request/fetch for your AsyncFetcher component. If you pass some customRequest
object as argument, that object could have some params
or postData
that will be used only for this request.
boolean
| defaults totrue
whenautoFetch={true}
orfalse
whenautoFetch={false}
This prop will indicate whether or not your AsyncFetcher component is in loading/fetching state.
any
| defaults tonull
This is the main result of your request when it done with success. As your response data it is parsed by axios, it could be some JSON/Javascript object or other kind of complex data.
any
| defaults tonull
This prop will be filled when your request/fetch it is completed without success. When you start a new fetch
this prop will be null
again until new fail happens.
object
| defaults tonull
This prop will be filled when your request/fetch it is completed and will have your complete request details beyond data
and error
info.
function(data:<object or func>)
| use like ReactsetState
function with some plain object (key -> value) or a function that eval some plain object
Since AsyncFetcher component controls his internal state for new changes you could create stateless components that uses AsyncFetcher and manage new params
and/or postData
internally without use component props.
You could call inside you render children function like set({ params: { userId: 1, active: 'Y' } })
to fill some new fresh params for your query request or could call set({ postData: { name: 'John', email: '[email protected]' } })
for your POST requests.
You can even manually reset your data
results calling set({ data: null })
, or using the set function to handle any other custom state variable than params
, postData
or data
, like set({ myCustom: 'var' })
. This custom state props will be avaible in state
prop.
object
| defaults tonull
Prop to access the current query params state that will be used in the next request/fetch cycle.
object
| defaults tonull
Prop to access the current request payload state that will be used in the next POST request/fetch cycle.
object
| defaults tonull
Prop to access the current custom state of your AsyncFetcher component that are not params
, postData
and data
.
Property | Default | Description |
---|---|---|
url | null |
The URL (only required prop) used for fetching your data. Can be some string or a function that evals and return a URL string. |
method | get |
The request method to be used when fetching some data ("get", "post", "put", "delete", "options") |
params | null |
A object or string that will be passed in your URL as query params |
postData | null |
A object or string that will be passed in your POST requests as axios data option (payload). If you need to post some payload with data please set method prop as post or put |
canFetch | true |
Indicates if new requests/fetchs are allowed to be done. Accepts boolean values or a function that receives the current params and return a boolean |
autoFetch | true |
Controls if AsyncFetcher can handle itself ("automagic") new requests when state (params and/or postData) changed and also the first fetch in component mount |
autoPreventDefault | true |
If the first argument of fetch function is a DOMEvent this prop will control when AsyncFetcher will call event.preventDefault() or not |
debounce | 0 |
Indicates how much milliseconds (positive number) the AsyncFetcher component will debounce consecutive requests after params or postData changes when autoFetch={true} . Recommended for autocomplete and/or autoFetch based forms |
headers | null |
A custom plain object with additional HTTP Headers for your request |
ajax | false |
Adds {'X-Requested-With': 'XMLHttpRequest'} to your request headers |
authToken | null |
Adds a authorization token (like JWT) to your request headers as {'Authorization': 'Bearer ${authToken}'} |
accepts | null |
Adds a Accept header to your request. Can be some mime string, array of mimes or function that evals and return a mime string |
contentType | null |
Adds a Content-Type header to your request. It's useful when you need to POST some json data. So you can use contentType="json" . It's expected common content types options as: json, xml, form, html and text. Or you could pass some complex mime like multipart/form-data |
responseType | null |
Indicates the type of data that the server will respond with. As axios documentation the options are: 'json', 'text', 'arraybuffer', 'blob', 'document', 'stream' |
withCredentials | false |
Indicates whether or not cross-site Access-Control requests should be made using credentials |
axiosConfig | null |
A custom plain object that extends the axios config object used in your request. This plain object it is useful to fill all the other axios documentation options that are not handle by default for AsyncFetcher like: timeout , transformRequest , transformResponse , auth , responseEncoding and etc |
transformError | null |
A optional transform callback for parse and change a possible error response when your request/fetch fails. This func/callback needs to return some string or plain object with error details |
onResponse | null |
A event callback that occurs when a request/fetch it is complete with success, it receives a state object with response , params , postData and set function |
onError | null |
A event callback that occurs when a request/fetch it is complete with error, it receives a first argument of error object and the second argument it is state object with response , params , postData and set function |