npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-async-fetcher

v1.0.1

Published

React component for asynchronous loading/fetch online data

Downloads

29

Readme

npm version npm downloads npm licence

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"
    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>
);

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 to null

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 to true when autoFetch={true} or false when autoFetch={false}

This prop will indicate whether or not your AsyncFetcher component is in loading/fetching state.

data

any | defaults to null

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 to null

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 to null

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 React setState 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.

params

object | defaults to null

Prop to access the current query params state that will be used in the next request/fetch cycle.

postData

object | defaults to null

Prop to access the current request payload state that will be used in the next POST request/fetch cycle.

state

object | defaults to null

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 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 |

License

MIT