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 |
|
19 | let canUseDOM = Boolean(
|
20 | typeof window !== 'undefined' &&
|
21 | window.document &&
|
22 | window.document.createElement
|
23 | );
|
24 |
|
25 | let idsUpdaterMap: Map<string, (v: string) => void> = new Map();
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | export function useId(defaultId?: string): string {
|
32 | let [value, setValue] = useState(defaultId);
|
33 | let nextId = useRef(null);
|
34 |
|
35 | let res = useSSRSafeId(value);
|
36 |
|
37 | let updateValue = useCallback((val) => {
|
38 | nextId.current = val;
|
39 | }, []);
|
40 |
|
41 | if (canUseDOM) {
|
42 | idsUpdaterMap.set(res, updateValue);
|
43 | }
|
44 |
|
45 | useLayoutEffect(() => {
|
46 | let r = res;
|
47 | return () => {
|
48 | idsUpdaterMap.delete(r);
|
49 | };
|
50 | }, [res]);
|
51 |
|
52 |
|
53 |
|
54 | useEffect(() => {
|
55 | let newId = nextId.current;
|
56 | if (newId) {
|
57 | nextId.current = null;
|
58 | setValue(newId);
|
59 | }
|
60 | });
|
61 |
|
62 | return res;
|
63 | }
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | export function mergeIds(idA: string, idB: string): string {
|
70 | if (idA === idB) {
|
71 | return idA;
|
72 | }
|
73 |
|
74 | let setIdA = idsUpdaterMap.get(idA);
|
75 | if (setIdA) {
|
76 | setIdA(idB);
|
77 | return idB;
|
78 | }
|
79 |
|
80 | let setIdB = idsUpdaterMap.get(idB);
|
81 | if (setIdB) {
|
82 | setIdB(idA);
|
83 | return idA;
|
84 | }
|
85 |
|
86 | return idB;
|
87 | }
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 | export function useSlotId(depArray: ReadonlyArray<any> = []): string {
|
95 | let id = useId();
|
96 | let [resolvedId, setResolvedId] = useValueEffect(id);
|
97 | let updateId = useCallback(() => {
|
98 | setResolvedId(function *() {
|
99 | yield id;
|
100 |
|
101 | yield document.getElementById(id) ? id : undefined;
|
102 | });
|
103 | }, [id, setResolvedId]);
|
104 |
|
105 | useLayoutEffect(updateId, [id, updateId, ...depArray]);
|
106 |
|
107 | return resolvedId;
|
108 | }
|