React component for asynchronous loading/fetch online data
AsyncFetcher it is a simple and useful React (web or native) component for asynchronous loading/fetch online data with help of axios.
Installation
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
Usage
The AsyncFetcher component is based in function as child render to enhance your render with useful callback functions and props.
"Automagic" simple GET
See this demo online
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> );
Manual "non-automagic" (autoFetch={false}) with query
See this demo online
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> );
Autocomplete search with debounce prop to delay future requests
See this demo online
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> );
Simple (and manual) POST request
See this demo online
import React from "react";
import AsyncFetcher from "react-async-fetcher";
const SimplePost = () => ( <AsyncFetcher method="post" c 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> );
More Examples
For more info and good examples (including Form Upload and usage with Formik) visit the website project.
Children Render Props
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.
fetch
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.
isLoading
boolean| defaults totruewhenautoFetch={true}orfalsewhenautoFetch={false}
This prop will indicate whether or not your AsyncFetcher component is in loading/fetching state.
data
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.
error
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.
response
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.
set
function(data:<object or func>)| use like ReactsetStatefunction 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: 'john@doe.com' } }) 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.
params
object| defaults tonull
Prop to access the current query params state that will be used in the next request/fetch cycle.
postData
object| defaults tonull
Prop to access the current request payload state that will be used in the next POST request/fetch cycle.
state
object| defaults tonull
Prop to access the current custom state of your AsyncFetcher component that are not params, postData and data.
Component Props
| 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 c. 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 |