Skip to content

Commit daba3fd

Browse files
author
Alex Cory
committed
adding support for on-demand http requests, onMount option for previous behavior of fetching on componentDidMount, baseUrl with syntax in each request, a lot of syntax everywhere lol
1 parent 9ffdce9 commit daba3fd

File tree

7 files changed

+189
-31
lines changed

7 files changed

+189
-31
lines changed

src/App.js

+114-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,130 @@
11
import React from 'react';
22
import './App.css';
33
import useFetch from './useFetch'
4+
import { useGet, usePost } from './main'
45

56
const App = () => {
6-
const [data, loading, error] = useFetch('https://api.etilbudsavis.dk/v2/dealerfront?country_id=DK')
7+
// const [data, loading, error, refetch] = useFetch('https://api.etilbudsavis.dk/v2/dealerfront?country_id=DK')
8+
// const handleClick = () => {
9+
// refetch()
10+
// }
11+
// const {data, loading, error, request} = useGet('https://api.etilbudsavis.dk/v2/dealerfront?country_id=DK')
12+
// const handleClick = () => {
13+
// Get()
14+
// }
715

16+
// console.log('DATA: ', data)
17+
18+
// const [data, loading, error] = usePost('https://jsonplaceholder.typicode.com/posts', {
19+
// body: JSON.stringify({
20+
// title: 'foo',
21+
// body: 'bar',
22+
// userId: 1
23+
// })
24+
// })
25+
26+
// WORKS 😍
27+
// const [data, loading, error, request] = useFetch({
28+
// url: 'https://jsonplaceholder.typicode.com/posts/1',
29+
// // baseUrl: '', // then you can do: request.post({ url: '/posts', body: {} })
30+
// headers: {
31+
// "Content-type": "application/json; charset=UTF-8"
32+
// },
33+
// // timeout: 1000,
34+
// // onMount: true, // run on component did mount
35+
// })
36+
37+
// const [data, loading, error, request] = useFetch('https://jsonplaceholder.typicode.com/posts/1')
38+
39+
// const { data, loading, error, request, get, post, patch, put, del } = useFetch('https://jsonplaceholder.typicode.com/posts/1')
40+
const { data, loading, error, request, get, post, patch, put, del } = useFetch({
41+
baseUrl: 'https://jsonplaceholder.typicode.com/posts'
42+
})
43+
44+
// useEffect(() => {
45+
// // on component did mount or use 'onMount' option above
46+
// request.get()
47+
// }, [request])
48+
49+
// const [data, loading, error, get] = useGet({
50+
// url: 'https://jsonplaceholder.typicode.com/posts/1'
51+
// })
52+
const handleClick = () => {
53+
// get('/1')
54+
// post('/', {
55+
// // params: '?no=way&something=true',
56+
// title: 'foo',
57+
// body: 'bar',
58+
// userId: 1
59+
// })
60+
// patch('/1', {
61+
// title: 'foo',
62+
// body: 'bar',
63+
// userId: 1
64+
// })
65+
// put('/1', {
66+
// title: 'foo',
67+
// body: 'bar',
68+
// userId: 1
69+
// })
70+
// del('/1')
71+
// request.get()
72+
// request.post({
73+
// // params: '?no=way&something=true',
74+
// title: 'foo',
75+
// body: 'bar',
76+
// userId: 1
77+
// })
78+
// request.patch({
79+
// title: 'foo',
80+
// body: 'bar',
81+
// userId: 1
82+
// })
83+
// request.put({
84+
// title: 'foo',
85+
// body: 'bar',
86+
// userId: 1
87+
// })
88+
// request.delete({
89+
// title: 'foo',
90+
// body: 'bar',
91+
// userId: 1
92+
// })
93+
// get()
94+
// post({
95+
// // params: '?no=way&something=true',
96+
// title: 'foo',
97+
// body: 'bar',
98+
// userId: 1
99+
// })
100+
// patch({
101+
// title: 'foo',
102+
// body: 'bar',
103+
// userId: 1
104+
// })
105+
// put({
106+
// title: 'foo',
107+
// body: 'bar',
108+
// userId: 1
109+
// })
110+
// del({
111+
// title: 'foo',
112+
// body: 'bar',
113+
// userId: 1
114+
// })
115+
}
116+
117+
118+
if (error) return 'Error...'
8119
if (loading) return 'Loading...'
9120

10121
return (
11122
<div className="App">
12123
<header className="App-header">
124+
<button onClick={handleClick}>CLICK</button>
13125
<code style={{ display: 'block' }}>
14-
<pre>{JSON.stringify(data[0], null, 2)}</pre>
126+
<pre>{JSON.stringify(data, null, 2)}</pre>
15127
</code>
16-
<a
17-
className="App-link"
18-
href="https://reactjs.org"
19-
target="_blank"
20-
rel="noopener noreferrer"
21-
22-
>
23-
Learn React
24-
</a>
25128
</header>
26129
</div>
27130
);

src/useDelete.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import useFetch from './useFetch'
22

33
export const useDelete = (url, options) => {
4-
const response = useFetch(url, {
4+
const { data, loading, error, del } = useFetch(url, {
55
method: 'DELETE',
66
...options
77
})
8-
return response
8+
return Object.assign([ data, loading, error, del ], { data, loading, error, del, delete: del })
99
}

src/useFetch.js

+65-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,66 @@
11
import { useEffect, useState, useCallback } from 'react'
22

3-
export function useFetch(url, options) {
4-
// if on server, return loading
5-
if (!global.window) return Object.assign([null, true, null], { data: null, loading: true, error: null })
3+
const isObject = obj => obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
4+
5+
export function useFetch(arg1, arg2) {
6+
let url = null
7+
let options = {}
8+
let onMount = false
9+
let baseUrl = ''
10+
let method = 'GET'
11+
12+
if (typeof arg1 === 'string') {
13+
url = arg1
14+
if (isObject(arg2)) options = arg2
15+
} else if (isObject(arg1)) {
16+
const fetchObj = arg1
17+
if (true) {
18+
// take out all the things that are not normal `fetch` options
19+
// need to take this out of scope so can set the variables below correctly
20+
let { url, onMount, timeout, baseUrl, ...rest } = fetchObj
21+
options = rest
22+
}
23+
if (fetchObj.url) url = fetchObj.url
24+
if (fetchObj.onMount) onMount = fetchObj.onMount
25+
if (fetchObj.method) method = fetchObj.method
26+
if (fetchObj.baseUrl) baseUrl = fetchObj.baseUrl
27+
}
628

729
const [data, setData] = useState(null)
8-
const [loading, setLoading] = useState(true)
30+
const [loading, setLoading] = useState(onMount)
931
const [error, setError] = useState(null)
1032

11-
const fetchData = useCallback(async () => {
33+
const fetchData = useCallback(method => async (fArg1, fArg2) => {
34+
let query = ''
35+
const fetchOptions = {}
36+
if (isObject(fArg1) && method !== 'GET') {
37+
fetchOptions.body = JSON.stringify(fArg1)
38+
} else if (baseUrl && typeof fArg1 === 'string') {
39+
url = baseUrl + fArg1
40+
if (isObject(fArg2)) fetchOptions.body = JSON.stringify(fArg2)
41+
}
42+
if (typeof fArg1 === 'string' && typeof fArg2 === 'string') {
43+
const base = fArg1
44+
query = fArg2
45+
url = base + query
46+
}
47+
1248
try {
1349
setLoading(true)
14-
const response = await fetch(url, options)
50+
const response = await fetch(url + query, {
51+
method,
52+
...options,
53+
...fetchOptions,
54+
})
1555
let data = null
1656
try {
1757
data = await response.json()
18-
} catch (Error) {
19-
data = await response.text()
58+
} catch (err) {
59+
try {
60+
data = await response.text()
61+
} catch (err) {
62+
setError(`Currently only supports JSON and Text response types: ${err}`)
63+
}
2064
}
2165
setData(data)
2266
setLoading(false)
@@ -25,11 +69,22 @@ export function useFetch(url, options) {
2569
}
2670
}, [url])
2771

72+
const get = useCallback(fetchData('GET'))
73+
const post = useCallback(fetchData('POST'))
74+
const patch = useCallback(fetchData('PATCH'))
75+
const put = useCallback(fetchData('PUT'))
76+
const del = useCallback(fetchData('DELETE'))
77+
78+
const request = { get, post, patch, put, del, delete: del }
79+
2880
useEffect(() => {
29-
fetchData()
81+
if (onMount) request[method.toLowerCase()]()
3082
}, [fetchData])
3183

32-
return Object.assign([data, loading, error], { data, loading, error })
84+
return Object.assign(
85+
[ data, loading, error, request ],
86+
{ data, loading, error, request, ...request }
87+
)
3388
}
3489

3590
export default useFetch

src/useGet.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import useFetch from './useFetch'
22

33
export const useGet = (url, options) => {
4-
const response = useFetch(url, {
4+
const { data, loading, error, get } = useFetch(url, {
55
method: 'GET',
66
...options
77
})
8-
return response
8+
return Object.assign([ data, loading, error, get ], { data, loading, error, get })
99
}

src/usePatch.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import useFetch from './useFetch'
22

33
export const usePatch = (url, options) => {
4-
const response = useFetch(url, {
4+
const { data, loading, error, patch } = useFetch(url, {
55
method: 'PATCH',
66
...options
77
})
8-
return response
8+
return Object.assign([ data, loading, error, patch ], { data, loading, error, patch })
99
}

src/usePost.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import useFetch from './useFetch'
22

33
export const usePost = (url, options) => {
4-
const response = useFetch(url, {
4+
const { data, loading, error, post } = useFetch(url, {
55
method: 'POST',
66
...options
77
})
8-
return response
8+
return Object.assign([ data, loading, error, post ], { data, loading, error, post })
99
}

src/usePut.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import useFetch from './useFetch'
22

33
export const usePut = (url, options) => {
4-
const response = useFetch(url, {
4+
const { data, loading, error, put } = useFetch(url, {
55
method: 'PUT',
66
...options
77
})
8-
return response
8+
return Object.assign([ data, loading, error, put ], { data, loading, error, put })
99
}

0 commit comments

Comments
 (0)