@app-elements/use-request
v2.1.4
Published
Connect a Component to the result of an API request.
Downloads
83
Readme
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:
- Sets auth headers by default
- Uses your configured
apiUrl
- Safely parses server response
- 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 endpointOrUid
s 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.