forked from inertiajs/inertia
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDeferred.ts
More file actions
55 lines (42 loc) · 1.48 KB
/
Copy pathDeferred.ts
File metadata and controls
55 lines (42 loc) · 1.48 KB
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
import { ReactNode, useEffect, useMemo, useState } from 'react'
import { router } from '.'
import usePage from './usePage'
const urlWithoutHash = (url: URL | Location): URL => {
url = new URL(url.href)
url.hash = ''
return url
}
const isSameUrlWithoutHash = (url1: URL | Location, url2: URL | Location): boolean => {
return urlWithoutHash(url1).href === urlWithoutHash(url2).href
}
interface DeferredProps {
children: ReactNode
fallback: ReactNode
data: string | string[]
}
const Deferred = ({ children, data, fallback }: DeferredProps) => {
if (!data) {
throw new Error('`<Deferred>` requires a `data` prop to be a string or array of strings')
}
const [loaded, setLoaded] = useState(false)
const pageProps = usePage().props
const keys = useMemo(() => (Array.isArray(data) ? data : [data]), [data])
useEffect(() => {
const removeListener = router.on('start', (e) => {
const isPartialVisit = e.detail.visit.only.length > 0 || e.detail.visit.except.length > 0
const isReloadingKey = e.detail.visit.only.find((key) => keys.includes(key))
if (isSameUrlWithoutHash(e.detail.visit.url, window.location) && (!isPartialVisit || isReloadingKey)) {
setLoaded(false)
}
})
return () => {
removeListener()
}
}, [])
useEffect(() => {
setLoaded(keys.every((key) => pageProps[key] !== undefined))
}, [pageProps, keys])
return loaded ? children : fallback
}
Deferred.displayName = 'InertiaDeferred'
export default Deferred