-
Notifications
You must be signed in to change notification settings - Fork 31
/
FetchProvider.js
98 lines (85 loc) · 2.57 KB
/
FetchProvider.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
import { Choose, LinkSolid, Text, Notification } from 'components/elements'
import React, { useCallback, useState, useEffect } from 'react'
import { useQueryState } from 'components/hook'
import queueMicrotask from 'queue-microtask'
import { urlVariations } from 'helpers'
import mql from '@microlink/mql'
import demoLinks from '../../../data/demo-links'
const ErrorMessage = ({ more }) => {
const text = 'The URL has something weird.'
return (
<Notification.Error>
<Choose>
<Choose.When condition={!!more}>
<Text as='span'>
{text}{' '}
<LinkSolid display='inline' color='red8' href={more}>
Report it.
</LinkSolid>
</Text>
</Choose.When>
<Choose.Otherwise>
<Text as='span'>{text}</Text>
</Choose.Otherwise>
</Choose>
</Notification.Error>
)
}
const fetch = (url, opts) => {
const variations = urlVariations(url)
const item = demoLinks.find(item => variations.includes(item.data.url))
return item || mql(url, opts)
}
const FetchProvider = ({ mqlOpts, children }) => {
const [status, setStatus] = useState('initial')
const [response, setResponse] = useState({})
const [error, setError] = useState(null)
const [warning, setWarning] = useState(null)
const [data, setData] = useState(null)
const [query, setQuery] = useQueryState()
const fetchData = useCallback(
async (url, opts) => {
try {
setQuery({ url, ...opts })
setError(null)
setStatus('fetching')
const doFetch = url => fetch(url, { ...mqlOpts, ...opts })
const { data, response } = Array.isArray(url)
? await Promise.all(url.map(doFetch))
: await doFetch(url)
setStatus('fetched')
setData(data)
setResponse(response)
} catch (err) {
console.error('FetchProvider:', err)
setStatus('error')
setError(err)
}
},
[mqlOpts, setQuery]
)
const doFetch = (url, opts) => {
setWarning(null)
if (url) return fetchData(url, opts)
queueMicrotask(() =>
setWarning({ children: 'You need to provide a valid URL.' })
)
}
// TODO: Use React.Suspense
/* eslint-disable*/
useEffect(() => {
queueMicrotask(() => {
const { url, ...opts } = query
if (url) fetchData(url, opts)
})
}, [])
/* eslint-enable */
return (
<>
{error && <ErrorMessage {...error} />}
{!error && warning && <Notification.Warning {...warning} />}
{children({ status, doFetch, data, response })}
</>
)
}
export default FetchProvider