-
Notifications
You must be signed in to change notification settings - Fork 129
/
index.js
114 lines (90 loc) 路 2.16 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import React from 'react'
import Axios from 'axios'
import LRU from 'lru-cache'
const actions = {
REQUEST_START: 'REQUEST_START',
REQUEST_END: 'REQUEST_END'
}
const initialState = {
loading: true
}
const ssrPromises = []
let cache = new LRU()
let axios = Axios
export function configure(options) {
if (options.axios) {
axios = options.axios
}
if (options.cache) {
cache = options.cache
}
}
export function loadCache(data) {
cache.load(data)
}
export async function serializeCache() {
await Promise.all(ssrPromises)
ssrPromises.length = 0
return cache.dump()
}
async function cacheAdapter(config) {
const cacheKey = JSON.stringify(config)
const hit = cache.get(cacheKey)
if (hit) {
return hit
}
delete config.adapter
const response = await axios(config)
const responseForCache = { ...response }
delete responseForCache.config
delete responseForCache.request
cache.set(cacheKey, responseForCache)
return response
}
function reducer(state, action) {
switch (action.type) {
case actions.REQUEST_START:
return {
...state,
loading: true
}
case actions.REQUEST_END:
return {
...state,
loading: false,
...(action.error ? {} : { data: action.payload.data }),
[action.error ? 'error' : 'response']: action.payload
}
default:
return state
}
}
async function request(config, dispatch) {
try {
dispatch({ type: actions.REQUEST_START })
const response = await axios(config)
dispatch({ type: actions.REQUEST_END, payload: response })
} catch (err) {
dispatch({ type: actions.REQUEST_END, payload: err, error: true })
}
}
export default function useAxios(config) {
if (typeof config === 'string') {
config = {
url: config
}
}
const [state, dispatch] = React.useReducer(reducer, initialState)
if (typeof window === 'undefined') {
ssrPromises.push(axios({ ...config, adapter: cacheAdapter }))
}
React.useEffect(() => {
request({ ...config, adapter: cacheAdapter }, dispatch)
}, [JSON.stringify(config)])
return [
state,
function refetch() {
return request(config, dispatch)
}
]
}