1
1
import { useEffect , useState , useCallback } from 'react'
2
2
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
+ }
6
28
7
29
const [ data , setData ] = useState ( null )
8
- const [ loading , setLoading ] = useState ( true )
30
+ const [ loading , setLoading ] = useState ( onMount )
9
31
const [ error , setError ] = useState ( null )
10
32
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
+
12
48
try {
13
49
setLoading ( true )
14
- const response = await fetch ( url , options )
50
+ const response = await fetch ( url + query , {
51
+ method,
52
+ ...options ,
53
+ ...fetchOptions ,
54
+ } )
15
55
let data = null
16
56
try {
17
57
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
+ }
20
64
}
21
65
setData ( data )
22
66
setLoading ( false )
@@ -25,11 +69,22 @@ export function useFetch(url, options) {
25
69
}
26
70
} , [ url ] )
27
71
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
+
28
80
useEffect ( ( ) => {
29
- fetchData ( )
81
+ if ( onMount ) request [ method . toLowerCase ( ) ] ( )
30
82
} , [ fetchData ] )
31
83
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
+ )
33
88
}
34
89
35
90
export default useFetch
0 commit comments