forked from TanStack/devtools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-location-changes.ts
More file actions
69 lines (53 loc) · 1.96 KB
/
use-location-changes.ts
File metadata and controls
69 lines (53 loc) · 1.96 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { onCleanup, onMount } from 'solid-js'
const LOCATION_CHANGE_EVENT = 'tanstack-devtools:locationchange'
type LocationChangeListener = () => void
const listeners = new Set<LocationChangeListener>()
let lastHref = ''
let teardownLocationObservation: (() => void) | undefined
function emitLocationChangeIfNeeded() {
const nextHref = window.location.href
if (nextHref === lastHref) return
lastHref = nextHref
listeners.forEach((listener) => listener())
}
function dispatchLocationChangeEvent() {
window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT))
}
function observeLocationChanges() {
if (teardownLocationObservation) return
lastHref = window.location.href
const originalPushState = window.history.pushState
const originalReplaceState = window.history.replaceState
const handleLocationSignal = () => {
emitLocationChangeIfNeeded()
}
window.history.pushState = function (...args) {
originalPushState.apply(this, args)
dispatchLocationChangeEvent()
}
window.history.replaceState = function (...args) {
originalReplaceState.apply(this, args)
dispatchLocationChangeEvent()
}
window.addEventListener('popstate', handleLocationSignal)
window.addEventListener('hashchange', handleLocationSignal)
window.addEventListener(LOCATION_CHANGE_EVENT, handleLocationSignal)
teardownLocationObservation = () => {
window.history.pushState = originalPushState
window.history.replaceState = originalReplaceState
window.removeEventListener('popstate', handleLocationSignal)
window.removeEventListener('hashchange', handleLocationSignal)
window.removeEventListener(LOCATION_CHANGE_EVENT, handleLocationSignal)
teardownLocationObservation = undefined
}
}
export function useLocationChanges(onChange: () => void) {
onMount(() => {
observeLocationChanges()
listeners.add(onChange)
onCleanup(() => {
listeners.delete(onChange)
if (listeners.size === 0) teardownLocationObservation?.()
})
})
}