1 | import useForceUpdate from './useForceUpdate';
|
2 | import useStableMemo from './useStableMemo';
|
3 | export class ObservableMap extends Map {
|
4 | constructor(listener, init) {
|
5 | super(init);
|
6 | this.listener = listener;
|
7 | }
|
8 | set(key, value) {
|
9 | super.set(key, value);
|
10 | // When initializing the Map, the base Map calls this.set() before the
|
11 | // listener is assigned so it will be undefined
|
12 | if (this.listener) this.listener(this);
|
13 | return this;
|
14 | }
|
15 | delete(key) {
|
16 | let result = super.delete(key);
|
17 | this.listener(this);
|
18 | return result;
|
19 | }
|
20 | clear() {
|
21 | super.clear();
|
22 | this.listener(this);
|
23 | }
|
24 | }
|
25 |
|
26 | /**
|
27 | * Create and return a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) that triggers rerenders when it's updated.
|
28 | *
|
29 | * ```tsx
|
30 | * const customerAges = useMap<number>([
|
31 | * ['john', 24],
|
32 | * ['betsy', 25]
|
33 | * ]);
|
34 | *
|
35 | * return (
|
36 | * <>
|
37 | * {Array.from(ids, ([name, age]) => (
|
38 | * <div>
|
39 | * {name}: {age}. <button onClick={() => ids.delete(name)}>X</button>
|
40 | * </div>
|
41 | * )}
|
42 | * </>
|
43 | * )
|
44 | * ```
|
45 | *
|
46 | * @param init initial Map entries
|
47 | */
|
48 | function useMap(init) {
|
49 | const forceUpdate = useForceUpdate();
|
50 | return useStableMemo(() => new ObservableMap(forceUpdate, init), []);
|
51 | }
|
52 | export default useMap; |
\ | No newline at end of file |