Skip to content

Commit

Permalink
Merge pull request #128 from danybeltran/feat-unnecesarystate
Browse files Browse the repository at this point in the history
feat(useFetch):
  • Loading branch information
danybeltran authored Jan 20, 2023
2 parents f778549 + 0a5f08f commit 85e7e8f
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 161 deletions.
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,44 @@
### HTTP React

React hooks for data fetching
React hooks for data fetching, built on top of the native `Fetch` API.

<p align="center">
<a href="https://www.npmjs.com/package/http-react" target="_blank"><img src="https://badge.fury.io/js/http-react.svg"></a>
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" />
<img src="https://github.com/atomic-state/http-react/actions/workflows/test.yml/badge.svg?event=push" />
</p>

Installation:
#### Overview

With one hook call, you get all the information about a request, and you can start making UIs that are more consistent and performant:

```jsx
import useFetch from 'http-react'

export default function App() {
const { data, loading, error } = useFetch('/api/user-info')

if (loading) return <p>Loading</p>

if (error) return <p>An error ocurred</p>

return <h2>Welcome, {data.name}</h2>
}
```

It supports many features that are needed in data fetching in modern applications, while giving developers full control over the request configuration:

- Server-Side Rendering
- React Native
- Request deduplication
- Suspense
- Refresh
- Retry on error
- qraphql

and [more](https://http-react.netlify.app/docs/tutorial-basics/request-config)!

#### Installation:

```bash
npm install --save http-react
Expand All @@ -20,5 +50,5 @@ Or
yarn add http-react
```

[Getting started](https://http-react.netlify.app)
[Getting started](https://http-react.netlify.app/docs/intro)

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "http-react",
"version": "2.5.9",
"version": "2.6.0",
"description": "React hooks for data fetching",
"main": "dist/index.js",
"scripts": {
Expand Down
181 changes: 24 additions & 157 deletions src/hooks/use-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export function useFetch<FetchDataType = any, BodyType = any>(
method = METHODS.GET as HTTP_METHODS,
headers = {} as Headers,
body = undefined as unknown as Body,
formatBody = (e) => JSON.stringify(e),
formatBody = e => JSON.stringify(e),

resolver = isFunction(ctx.resolver) ? ctx.resolver : DEFAULT_RESOLVER,
onError,
Expand Down Expand Up @@ -132,15 +132,15 @@ export function useFetch<FetchDataType = any, BodyType = any>(
? optionsConfig.retryOnReconnect
: ctx.retryOnReconnect

const [reqQuery, setReqQuery] = useState({
const reqQuery = {
...ctx.query,
...config.query
})
}

const [reqParams, setReqParams] = useState({
const reqParams = {
...ctx.params,
...config.params
})
}

const rawUrl =
(hasBaseUrl(url)
Expand All @@ -164,12 +164,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(

const resolvedKey = serialize({ idString })

const [configUrl, setConfigUrl] = useState(urls[resolvedKey])

useEffect(() => {
setConfigUrl(urls[resolvedKey])
}, [serialize(urls[resolvedKey])])

const suspense = $suspense || willSuspend[resolvedKey]

if (suspense && !willSuspend[resolvedKey]) {
Expand All @@ -188,17 +182,10 @@ export function useFetch<FetchDataType = any, BodyType = any>(
}
}

useEffect(() => {
if (url !== '') {
setReqParams(() => {
const newParams = {
...ctx.params,
...config.params
}
return newParams
})
}
}, [serialize({ ...ctx.params, ...config.params }), resolvedKey])
const configUrl = urls[resolvedKey] || {
realUrl,
rawUrl
}

const stringDeps = serialize(
Object.assign(
Expand Down Expand Up @@ -254,39 +241,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(
}
}, [])

useEffect(() => {
let queryParamsFromString: any = {}
try {
// getting query params from passed url
const queryParts = qp.split('&')
queryParts.forEach((q, i) => {
const [key, value] = q.split('=')
if (queryParamsFromString[key] !== value) {
queryParamsFromString[key] = `${value}`
}
})
} finally {
if (url !== '') {
setReqQuery(() => {
const newQuery = {
...ctx.query,
...queryParamsFromString,
...config.query
}
return newQuery
})
}
}
}, [
resolvedKey,
requestCallId,
serialize({
qp,
...ctx.query,
...config.query
})
])

const requestCache = cacheProvider.get(resolvedKey)

const initialDataValue = isDefined(valuesMemory[resolvedKey])
Expand All @@ -304,13 +258,11 @@ export function useFetch<FetchDataType = any, BodyType = any>(

const [online, setOnline] = useState(true)

const [requestHeaders, setRequestHeades] = useState<
object | Headers | undefined
>({ ...ctx.headers, ...config.headers })

const [response, setResponse] = useState<CustomResponse<FetchDataType>>()
const requestHeaders = {
...ctx.headers,
...config.headers
}

const [statusCode, setStatusCode] = useState<number>()
const [error, setError] = useState<any>(hasErrors[resolvedKey])
const [loading, setLoading] = useState(
revalidateOnMount
Expand All @@ -320,21 +272,10 @@ export function useFetch<FetchDataType = any, BodyType = any>(
: previousConfig[resolvedKey] !== serialize(optionsConfig)
)
const [completedAttempts, setCompletedAttempts] = useState(0)

const [requestAbortController, setRequestAbortController] =
useState<AbortController>(new AbortController())

const [reqMethod, setReqMethod] = useState(config.method)

useEffect(() => {
if (url !== '') {
setReqMethod(config.method)
requestsProvider.emit(resolvedKey, {
requestCallId,
method: config.method
})
}
}, [stringDeps, response, requestAbortController, requestCallId])

useEffect(() => {
if (url !== '') {
if (error && !hasErrors[resolvedKey]) {
Expand Down Expand Up @@ -385,7 +326,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(
if (previousConfig[resolvedKey] !== serialize(optionsConfig)) {
previousProps[resolvedKey] = optionsConfig
queue(() => {
setReqMethod(config.method)
if (url !== '') {
const newUrls = {
realUrl,
Expand All @@ -394,10 +334,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(

urls[resolvedKey] = newUrls

setConfigUrl({
rawUrl,
realUrl
})
requestsProvider.emit(resolvedKey, {
requestCallId,
realUrl: resKey,
Expand Down Expand Up @@ -513,7 +449,7 @@ export function useFetch<FetchDataType = any, BodyType = any>(
})
} else {
if (_data.errors && isGqlRequest) {
setData((previous) => {
setData(previous => {
const newData = {
...previous,
variables: (optionsConfig as any)?.variables,
Expand Down Expand Up @@ -728,54 +664,16 @@ export function useFetch<FetchDataType = any, BodyType = any>(
// onResolve($data, lastResponses[resolvedKey])
}
}
if (isDefined(method)) {
queue(() => {
setReqMethod(method)
})
}
if (isDefined(config?.query)) {
queue(() => {
setReqQuery(config.query)
})
}
if (isDefined(rawUrl) && isDefined(realUrl)) {
queue(() => {
setConfigUrl({
rawUrl,
realUrl
})
})
}
if (isDefined(config?.params)) {
queue(() => {
setReqParams(config?.params)
})
}
if (isDefined(config?.headers)) {
queue(() => {
setRequestHeades(config?.headers)
})
}
if (isDefined(completedAttempts)) {
queue(() => {
setCompletedAttempts(completedAttempts)
})
}
if (isDefined(code)) {
queue(() => {
setStatusCode(code)
})
}
if (isDefined(requestAbortController)) {
queue(() => {
setRequestAbortController(requestAbortController)
})
}
if (isDefined(response)) {
queue(() => {
setResponse(response)
})
}
if (isDefined(loading)) {
queue(() => {
setLoading(loading)
Expand Down Expand Up @@ -857,19 +755,12 @@ export function useFetch<FetchDataType = any, BodyType = any>(
loading: true,
error: null
})
const reqQ = {
...ctx.query,
...config.query
}
const reqP = {
...ctx.params,
...config.params
}

fetchData({
query: Object.keys(reqQ)
.map((q) => [q, reqQ[q]].join('='))
query: Object.keys(reqQuery)
.map(q => [q, reqQuery[q]].join('='))
.join('&'),
params: reqP
params: reqParams
})
}
}
Expand Down Expand Up @@ -964,14 +855,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(
}
}, [onOffline, reValidate, resolvedKey, retryOnReconnect])

useEffect(() => {
const newHeaders = {
...ctx.headers,
...config.headers
}
setRequestHeades(newHeaders)
}, [serialize({ ...ctx.headers, ...config.headers }), resolvedKey])

useEffect(() => {
if (revalidateOnMount) {
if (suspense) {
Expand All @@ -992,7 +875,7 @@ export function useFetch<FetchDataType = any, BodyType = any>(
if (error) {
if (completedAttempts < (attempts as number)) {
reValidate()
setCompletedAttempts((previousAttempts) => {
setCompletedAttempts(previousAttempts => {
let newAttemptsValue = previousAttempts + 1

requestsProvider.emit(resolvedKey, {
Expand Down Expand Up @@ -1040,19 +923,11 @@ export function useFetch<FetchDataType = any, BodyType = any>(
if (isPending(resolvedKey)) {
setLoading(true)
}
const reqQ = {
...ctx.query,
...config.query
}
const reqP = {
...ctx.params,
...config.params
}
fetchData({
query: Object.keys(reqQ)
.map((q) => [q, reqQ[q]].join('='))
query: Object.keys(reqQuery)
.map(q => [q, reqParams[q]].join('='))
.join('&'),
params: reqP
params: reqParams
})
}
// It means a url is not passed
Expand Down Expand Up @@ -1160,7 +1035,6 @@ export function useFetch<FetchDataType = any, BodyType = any>(
...config,
...optionsConfig,
...previousProps[resolvedKey],
method: reqMethod,
params: {
...reqParams,
...previousProps[resolvedKey]?.params
Expand Down Expand Up @@ -1263,14 +1137,7 @@ export function useFetch<FetchDataType = any, BodyType = any>(
}
}
}
}, [
url,
auto,
cancelOnChange,
serialize(id),
serialize(optionsConfig),
resolvedKey
])
}, [serialize(optionsConfig)])

const resolvedData = React.useMemo(() => data, [rawJSON])

Expand Down

0 comments on commit 85e7e8f

Please sign in to comment.