@harryy/rehttp
v1.4.1
Published
Highly customizable http client library for react
Readme
React + HTTP = ReHttp
A highly customizable http client library for react
Features
- [x] No bloated dependencies
- [x] Optional global configuration
- [x] Typescript support
- [x] Promise based
- [x] Hooks for function component
- [x] Lazy fetch support
- [x] Transforming request and response
- [x] Callbacks for request, response and error
- [x] Caching
- [x] Use outside of react context
- [x] Component (for class based component)
Installation
Yarn:
yarn add @harryy/rehttpNPM:
npm install @harryy/rehttpUsage
import React from 'react'
import { useReHttp } from 'rehttp'
const Example: React.FC = () => {
const {data, refetch, loading} = useReHttp({
url: 'https://jsonplaceholder.typicode.com/posts/1'
})
if (loading) {
return <>Loading...</>
}
return (
<>
{data.title}
<button onClick={() => refetch()}>Refetch</button>
</>
)
}API
const {data, response, error, loading, execute, isRequestInFlight, cached} = useReHttp(request, options?)
By default, request will be fired if lazy: true is not passed as an option.
data contains json serialized data
response contains the raw response from the server
error contains the error if any
loading is true only when there is no data or error
isRequestInFlight tells whether the request is in flight or not
execute can be called with optional request parameters to refetch data again
cached gives the cached object if the request was cached earlier
import React from 'react'
import { useReHttp, ReHttpRequest, ReHttpResponse } from 'rehttp'
interface Post {
id: string,
title: string,
}
interface PostError {
message: string,
status: 'NOTOK',
}
useReHttp<Post, PostError>({
method: 'GET', // Optional, type: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT', default: 'GET'
url: 'https://jsonplaceholder.typicode.com/posts', // Optional, type: string, default: ''
headers: {
Accept: 'application/json'
}, // Optional, type: Record<string, string>, default: undefined
params: {
page: 1,
per_page: 5,
tags: ['hello', 'world']
}, // Optional, type: Record<string, string | number | Array<string | number>>, default: undefined
body: undefined // Optional, type: any, default: undefined
}, {
transformError: async (e) => {
return {
status: 'NOTOK',
message: e.message
}
}, // Optional, type: (data: any) => Promise<PostError>, default: undefined
transformResponse: async (data: any, response: ReHttpResponse) => {
if (data.id && response.status === 200) {
return {
id: data.id,
title: data.title.toUpperCase()
}
} else {
return Promise.reject(new Error('Post has no id'))
}
}, // Optional, type: (data: any, response: ReHttpResponse) => Promise<Post>, default: undefined
transformRequest: async (res: ReHttpRequest) => {
const token = await SomeAsyncStorageOrApiOrWhatever().token
return {
...res,
params: {
foo: 'bar',
},
headers: {
Authorization: `Bearer ${token}`
}
}
}, // Optional, type: (data: ReHttpRequest) => Promise<ReHttpRequest>, default: undefined
lazy: true, // Optional, type: boolean, default: false
noCache: true, // Optional, type: boolean, default: false
});Need to use in class component? No Problem!
import React from 'react'
import { ReHttp, ReHttpProps } from 'rehttp'
interface Post {
id: string,
title: string,
}
interface PostError {
message: string,
status: 'NOTOK',
}
class MyComponent extends React.Component {
reHttpProps: Omit<ReHttpProps<Post, PostError>, 'children'> = {
method: 'GET', // Optional, type: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT', default: 'GET'
url: 'https://jsonplaceholder.typicode.com/posts', // Optional, type: string, default: ''
headers: {
Accept: 'application/json'
}, // Optional, type: Record<string, string>, default: { Accept: 'application/json', 'Content-Type': 'application/json' }
params: {
page: 1,
per_page: 5,
tags: ['hello', 'world']
}, // Optional, type: Record<string, string | number | Array<string | number>>, default: undefined
body: undefined, // Optional, type: any, default: undefined
onRequest: () => {
showLoader()
}, //Optional, type: (data: ReHttpRequest) => Promise<void>
onResponse: () => {
showSuccess('request success')
}, //Optional, type: (data: Post, response: ReHttpResponse) => Promise<void>
onError: (error) => {
showAlert(error.message)
}, // Optional, type: (error: PostError) => Promise<void>
transformError: async (e) => {
return {
status: 'NOTOK',
message: e.message
}
}, // Optional, type: (data: any) => Promise<PostError>, default: undefined
transformResponse: async (data: any, response: ReHttpResponse) => {
if (data.id && response.status === 200) {
return {
id: data.id,
title: data.title.toUpperCase()
}
} else {
return Promise.reject(new Error('Post has no id'))
}
}, // Optional, type: (data: any, response: ReHttpResponse) => Promise<Post>, default: undefined
transformRequest: async (res: ReHttpRequest) => {
const token = await SomeAsyncStorageOrApiOrWhatever().token
return {
...res,
params: {
foo: 'bar',
},
headers: {
Authorization: `Bearer ${token}`
}
}
}, // Optional, type: (data: ReHttpRequest) => Promise<ReHttpRequest>, default: undefined
lazy: true, // Optional, type: boolean, default: false
noCache: true, // Optional, type: boolean, default: false
}
render() {
<ReHttp<Post, PostError> {...this.reHttpProps}>
{
({data, refetch}) => (
<>
{data.title}
<button onClick={() => refetch()}>Refetch</button>
</>
)
</ReHttp>
}
}Need to set options globally? No problem!
ReHttpProvider
import React from 'react'
import { ReHttpProvider, ReHttpProviderProps, ReHttpRequest, ReHttpResponse, InMemoryAdapter } from 'rehttp'
const App: React.FC = () => {
const options: ReHttpProviderProps = {
cacheAdapter: new InMemoryAdapter({ttl: 5 * 60 * 1000, size: 50}), // Optional, type: CacheAdapter, params: {ttl?: 5 * 60* 1000, size?: 50}?, ttl is in milliseconds
cacheMethods: ['GET'], // Optional, type: Array<ReHttpRequest['method']>, default: ['GET'], http methods that needs to be cached
baseUrl: 'https://jsonplaceholder.typicode.com', // Optional, type: string
method: 'GET', // Optional, type: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT'
params: {}, // Optional, type: Record<string, string | number | Array<string | number>>
headers: {}, // Optional, type: Record<string, string>
onRequest: () => {
showLoader()
}, //Optional, type: (data: ReHttpRequest) => Promise<void>
onResponse: () => {
showSuccess('request success')
}, //Optional, type: (data: any, response: ReHttpResponse) => Promise<void>
onError: (error) => {
showAlert(error.message)
}, // Optional, type: (error: any) => Promise<void>
onComplete: (dataOrError, response) => {
hideLoader()
}, // Optional, type: (dataOrError: any, response?: ReHttpResponse) => Promise<void>
transformError: async (e) => {
return {
status: 'NOTOK',
message: e.message
}
}, // Optional, type: (data: any) => Promise<PostError>, default: undefined
transformResponse: async (data: any, response: ReHttpResponse) => {
if (data.id && response.status === 200) {
return {
id: data.id,
title: data.title.toUpperCase()
}
} else {
return Promise.reject(new Error('Post has no id'))
}
}, // Optional, type: (data: any, response: ReHttpResponse) => Promise<Post>, default: undefined
transformRequest: async (res: ReHttpRequest) => {
const token = await SomeAsyncStorageOrApiOrWhatever().token
return {
...res,
params: {
foo: 'bar',
},
headers: {
Authorization: `Bearer ${token}`
}
}
}, // Optional, type: (data: ReHttpRequest) => Promise<ReHttpRequest>, default: undefined
lazy: true, // Optional, type: boolean
}
return (
<ReHttpProvider {...options}>
<Main />
</ReHttpProvider>
)
}Need to use it outside of react context (like redux thunk etc.) and still use context values? No Problem!
reHttpInstance
import React from 'react'
import { reHttpInstance } from 'rehttp'
reHttpInstance({
url: 'https://jsonplaceholder.typicode.com'
}).then(res => {
console.log('Response from ReHttp', res)
}) // option lazy: true will have no effect here
const MyComponent: React.FC = () => {
return <div>Hello World!</div>
}License
MIT © harryy2510
