forked from molefrog/wouter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuse-search-params.js
49 lines (37 loc) · 1.32 KB
/
use-search-params.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
import { useEffect, useState } from "./react-deps.js";
export default () => {
const [path] = useState(location.pathname);
const [search, update] = useState(location.search);
useEffect(() => {
patchHistoryEvents();
const events = ["popstate", "pushState", "replaceState"];
const handler = () => update(location.search);
events.map(e => addEventListener(e, handler));
return () => events.map(e => removeEventListener(e, handler));
}, []);
return [
Array.from(new URLSearchParams(search)),
(searchParams, replace) =>
history[replace ? "replaceState" : "pushState"](0, 0, `${path}?${searchParams.map(([k, v]) => `${k}=${v}`).join("&")}`)
];
};
// While History API does have `popstate` event, the only
// proper way to listen to changes via `push/replaceState`
// is to monkey-patch these methods.
//
// See https://stackoverflow.com/a/4585031
let patched = 0
const patchHistoryEvents = () => {
if (patched) return;
["pushState", "replaceState"].map(type => {
const original = history[type];
history[type] = function () {
const result = original.apply(this, arguments);
const event = new Event(type);
event.arguments = arguments;
dispatchEvent(event);
return result;
};
});
return (patched = 1);
};