1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | import {useCallback, useEffect, useRef, useState} from 'react';
|
14 | import {useLayoutEffect} from './useLayoutEffect';
|
15 | import {useSSRSafeId} from '@react-aria/ssr';
|
16 | import {useValueEffect} from './';
|
17 |
|
18 | let idsUpdaterMap: Map<string, (v: string) => void> = new Map();
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | export function useId(defaultId?: string): string {
|
25 | let [value, setValue] = useState(defaultId);
|
26 | let nextId = useRef(null);
|
27 |
|
28 | let res = useSSRSafeId(value);
|
29 |
|
30 | let updateValue = useCallback((val) => {
|
31 | nextId.current = val;
|
32 | }, []);
|
33 |
|
34 | idsUpdaterMap.set(res, updateValue);
|
35 |
|
36 | useLayoutEffect(() => {
|
37 | let r = res;
|
38 | return () => {
|
39 | idsUpdaterMap.delete(r);
|
40 | };
|
41 | }, [res]);
|
42 |
|
43 |
|
44 |
|
45 | useEffect(() => {
|
46 | let newId = nextId.current;
|
47 | if (newId) {
|
48 | nextId.current = null;
|
49 | setValue(newId);
|
50 | }
|
51 | });
|
52 |
|
53 | return res;
|
54 | }
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | export function mergeIds(idA: string, idB: string): string {
|
61 | if (idA === idB) {
|
62 | return idA;
|
63 | }
|
64 |
|
65 | let setIdA = idsUpdaterMap.get(idA);
|
66 | if (setIdA) {
|
67 | setIdA(idB);
|
68 | return idB;
|
69 | }
|
70 |
|
71 | let setIdB = idsUpdaterMap.get(idB);
|
72 | if (setIdB) {
|
73 | setIdB(idA);
|
74 | return idA;
|
75 | }
|
76 |
|
77 | return idB;
|
78 | }
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | export function useSlotId(depArray: ReadonlyArray<any> = []): string {
|
86 | let id = useId();
|
87 | let [resolvedId, setResolvedId] = useValueEffect(id);
|
88 | let updateId = useCallback(() => {
|
89 | setResolvedId(function *() {
|
90 | yield id;
|
91 |
|
92 | yield document.getElementById(id) ? id : null;
|
93 | });
|
94 | }, [id, setResolvedId]);
|
95 |
|
96 | useLayoutEffect(updateId, [id, updateId, ...depArray]);
|
97 |
|
98 | return resolvedId;
|
99 | }
|