-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathuseDom.tsx
85 lines (69 loc) · 1.91 KB
/
useDom.tsx
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import * as React from 'react';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import canUseDom from 'rc-util/lib/Dom/canUseDom';
import OrderContext from './Context';
import type { QueueCreate } from './Context';
const EMPTY_LIST = [];
/**
* Will add `div` to document. Nest call will keep order
* @param render Render DOM in document
*/
export default function useDom(
render: boolean,
debug?: string,
): [HTMLDivElement, QueueCreate] {
const [ele] = React.useState(() => {
if (!canUseDom()) {
return null;
}
const defaultEle = document.createElement('div');
if (process.env.NODE_ENV !== 'production' && debug) {
defaultEle.setAttribute('data-debug', debug);
}
return defaultEle;
});
// ========================== Order ==========================
const appendedRef = React.useRef(false);
const queueCreate = React.useContext(OrderContext);
const [queue, setQueue] = React.useState<VoidFunction[]>(EMPTY_LIST);
const mergedQueueCreate =
queueCreate ||
(appendedRef.current
? undefined
: (appendFn: VoidFunction) => {
setQueue(origin => {
const newQueue = [appendFn, ...origin];
return newQueue;
});
});
// =========================== DOM ===========================
function append() {
if (!ele.parentElement) {
document.body.appendChild(ele);
}
appendedRef.current = true;
}
function cleanup() {
ele.parentElement?.removeChild(ele);
appendedRef.current = false;
}
useLayoutEffect(() => {
if (render) {
if (queueCreate) {
queueCreate(append);
} else {
append();
}
} else {
cleanup();
}
return cleanup;
}, [render]);
useLayoutEffect(() => {
if (queue.length) {
queue.forEach(appendFn => appendFn());
setQueue(EMPTY_LIST);
}
}, [queue]);
return [ele, mergedQueueCreate];
}