@app-elements/use-request

2.1.4 • Public • Published

useRequest

useRequest is a simple hook for loading data. It's efficient and caches results automatically.

Installation

npm install --save @app-elements/use-request

Usage

import { useRequest } from '@app-elements/use-request'
import createStore from 'atom'

const store = createStore([], {})

const Users = () => {
  // return an object with the keys: result, clear
  // result is the JSON response from the given URL.
  // clear is a function to clear the cache, and reload the data from the URL.
  const { result, error, isLoading, clear } = useRequest(store, 'https://jsonplaceholder.typicode.com/users')
  if (isLoading) {
    return <div>Loading...</div>
  }
  if (error != null) {
    return <div>Error!</div>
  }
  return (
    <ul>
      {result.map(({ name }) => <li>{name}</li>)}
    </ul>
  )
}

Dependent Fetching

Sometimes you need to load a request based on data from another request. Here's how you can orchestrate that:

const { result: user } = useRequest(store, '/api/user')
const { result: projects } = useRequest(store, user != null ? `/api/user/${user.id}/projects` : null)

Making a Request Without Hooks

The core request function that useRequest utilizes comes with some nice defaults that you may want to reuse outside of a hook context:

  1. Sets auth headers by default
  2. Uses your configured apiUrl
  3. Safely parses server response
  4. Unlike Fetch, the promise fails if the status code is >= 400
import { request } from '@app-elements/use-request/request'

const { promise, xhr } = request({
  url: 'https://my-cool-api.com/resource',
  method: 'POST',
  data: {
    // ...
  }
})

Request Reducer

useRequest also ships with an optional reducer and actions that help with managing the cached request results. To use it, you must import the reducer and include it when creating your store.

import { requestsReducer, actions as requestActions } from '@app-elements/use-request/reducer'

const store = createStore([requestsReducer], initialState)

// It's also convenient to export the actions from your store file:
export const clearRequest = requestActions.clearRequest
export const clearRequests = requestActions.clearRequests
export const patchListRequest = requestActions.patchListRequest

appendRequest

appendRequest({ endpointOrUid: String, item: Object, path?: String }): FluxStandardAction

This is for appending a new item for an endpoint that represents an array of items to render, ex. api/listings. Say, you create a new listing, instead of getting the whole listing array from your API again, you can just append the new listing to the end of the existing array of items you have.

appendRequest({
  endpointOrUid: '/users',
  path: '',
  item: { id: 6, name: 'Margo' }
})

clearRequest

clearRequest(endpointOrUid: String): FluxStandardAction

Removes the matching endpointOrUid from the requests object.

clearRequest('/api/listings')

clearRequests

clearRequests(predicate: Function): FluxStandardAction

Filters out any endpointOrUids on the requests object that match the predicate function.

clearRequests(uid => uid.indexOf('listings') > -1)

patchListRequest

patchListRequest({ endpointOrUid: String, dataToMerge: Object, matchKey?: String, path?: String }): FluxStandardAction

This is for patching an endpoint that represents an array of items to render, ex. api/listings. Let's say you are rendering this array of items, and then perform an update to one of the items contained in that array. When you go back to view the list, it very likely contains that one item but with outdated data. You could clear the entire listings request, re-rendering the whole list, but it would be much nicer to just update the one item in the listings that we know has updated. This way, the entire list isn't re-rendered, rather only the one item.

patchListRequest({
  endpointOrUid: '/api/listings',
  dataToMerge: { id: 4, title: 'Updated title' }, // Must include the `matchKey` value. In this case, `id: 4`.
  matchKey = 'id', // Optional, defaults to 'id'.
  path = 'results' // Optional, defaults to 'results'. This matches the response shape of Django-Rest-Framework. It should be the path to the actual array data returned in the API response.
})

Props

Prop Type Default Description
store Object None An (atom) store instance
url String None A URL to GET data from
options Object None Various options to customize your request

Request Options

Prop Type Default Description
maxTime Number 30000 Time (ms) to cache result
uid String None A unique ID to store cached result under
headers Object None Your request headers
method String None Request method
data Object None Data to send. Typically with POST or PATCH requests
noAuth Boolean false Skip automatically setting the Authorization header
contentType String 'application/json' Set the Content-Type, or falsy for no Content-Type header

Return values

Prop Type Description
result JSON The body returned by the request. Could be null, or a string if not a JSON endpoint.
error Error If the response header is >= 400, this will contain an Error instance.
isLoading Boolean true until either result or error is set.
clear Function Call this to clear the cached result of the request.

Package Sidebar

Install

npm i @app-elements/use-request

Weekly Downloads

1

Version

2.1.4

License

ISC

Unpacked Size

256 kB

Total Files

15

Last publish

Collaborators

  • coryschadt
  • trustfall
  • adriaanwm
  • staydecent