Skip to content

Commit b80be5a

Browse files
committed
refactor: Each Portal control self lock
1 parent af65767 commit b80be5a

File tree

4 files changed

+62
-78
lines changed

4 files changed

+62
-78
lines changed

docs/examples/basic.less

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.abs {
2+
position: absolute;
3+
z-index: 999999;
4+
left: 0;
5+
background: red;
6+
}
7+
8+
.root {
9+
top: 0;
10+
}
11+
12+
.parent {
13+
top: 50px;
14+
}
15+
16+
.children {
17+
top: 100px;
18+
}

docs/examples/basic.tsx

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import React, { version } from 'react';
2+
import classNames from 'classnames';
23
import Portal from '../../src';
4+
import './basic.less';
35

46
export default () => {
57
const [show, setShow] = React.useState(true);
@@ -16,46 +18,41 @@ export default () => {
1618
);
1719

1820
const getContainer = customizeContainer ? () => divRef.current : undefined;
21+
const contentCls = customizeContainer ? '' : 'abs';
1922

2023
return (
2124
<React.StrictMode>
22-
<div style={{ border: '2px solid red' }}>
23-
Real Version: {version}
24-
<button onClick={() => setShow(!show)}>show: {show.toString()}</button>
25-
<button onClick={() => setCustomizeContainer(!customizeContainer)}>
26-
customize container: {customizeContainer.toString()}
27-
</button>
28-
<button onClick={() => setLock(!lock)}>
29-
lock scroll: {lock.toString()}
30-
</button>
31-
<div
32-
id="customize"
33-
ref={divRef}
34-
style={{ border: '1px solid green', minHeight: 10 }}
35-
/>
36-
</div>
25+
<div style={{ height: '200vh' }}>
26+
<div style={{ border: '2px solid red' }}>
27+
Real Version: {version}
28+
<button onClick={() => setShow(!show)}>
29+
show: {show.toString()}
30+
</button>
31+
<button onClick={() => setCustomizeContainer(!customizeContainer)}>
32+
customize container: {customizeContainer.toString()}
33+
</button>
34+
<button onClick={() => setLock(!lock)}>
35+
lock scroll: {lock.toString()}
36+
</button>
37+
<div
38+
id="customize"
39+
ref={divRef}
40+
style={{ border: '1px solid green', minHeight: 10 }}
41+
/>
42+
</div>
3743

38-
<Portal open={show} getContainer={getContainer} autoLock={lock}>
39-
<p>Hello Root</p>
4044
<Portal open={show} getContainer={getContainer} autoLock={lock}>
41-
<p>Hello Parent</p>
45+
<p className={classNames(contentCls, 'root')}>Hello Root</p>
4246
<Portal open={show} getContainer={getContainer} autoLock={lock}>
43-
<p>Hello Children</p>
47+
<p className={classNames(contentCls, 'parent')}>Hello Parent</p>
48+
<Portal open={show} getContainer={getContainer} autoLock={lock}>
49+
<p className={classNames(contentCls, 'children')}>
50+
Hello Children
51+
</p>
52+
</Portal>
4453
</Portal>
4554
</Portal>
46-
</Portal>
47-
48-
<div
49-
style={{
50-
position: 'absolute',
51-
top: 0,
52-
right: 0,
53-
height: '200vh',
54-
width: 1,
55-
background: 'yellow',
56-
zIndex: -1,
57-
}}
58-
/>
55+
</div>
5956
</React.StrictMode>
6057
);
6158
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
},
4343
"dependencies": {
4444
"@babel/runtime": "^7.18.0",
45+
"classnames": "^2.3.2",
4546
"rc-util": "^5.8.0"
4647
},
4748
"devDependencies": {

src/useScrollLocker.tsx

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
import * as React from 'react';
22
import { updateCSS, removeCSS } from 'rc-util/lib/Dom/dynamicCSS';
3-
import useLayoutEffect, {
4-
useLayoutUpdateEffect,
5-
} from 'rc-util/lib/hooks/useLayoutEffect';
3+
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
64
import getScrollBarSize from 'rc-util/lib/getScrollBarSize';
75
import { isBodyOverflowing } from './util';
86

9-
let lockCount = 0;
10-
let locked = false;
11-
127
const UNIQUE_ID = `rc-util-locker-${Date.now()}`;
138

14-
function syncLocker() {
15-
const nextLocked = lockCount > 0;
9+
let uuid = 0;
1610

17-
if (locked !== nextLocked) {
18-
locked = nextLocked;
11+
export default function useScrollLocker(lock?: boolean) {
12+
const mergedLock = !!lock;
13+
const [id] = React.useState(() => {
14+
uuid += 1;
15+
return `${UNIQUE_ID}_${uuid}`;
16+
});
1917

20-
if (locked) {
18+
useLayoutEffect(() => {
19+
if (mergedLock) {
2120
const scrollbarSize = getScrollBarSize();
2221
const isOverflow = isBodyOverflowing();
2322

@@ -27,45 +26,14 @@ html body {
2726
overflow-y: hidden;
2827
${isOverflow ? `width: calc(100% - ${scrollbarSize}px);` : ''}
2928
}`,
30-
UNIQUE_ID,
29+
id,
3130
);
3231
} else {
33-
removeCSS(UNIQUE_ID);
32+
removeCSS(id);
3433
}
35-
}
36-
}
3734

38-
export default function useScrollLocker(lock?: boolean) {
39-
const mergedLock = !!lock;
40-
41-
// Init only check lock
42-
useLayoutEffect(() => {
43-
if (mergedLock) {
44-
lockCount += 1;
45-
syncLocker();
46-
}
47-
}, []);
48-
49-
// Update will both check the lock state
50-
useLayoutUpdateEffect(() => {
51-
if (mergedLock) {
52-
lockCount += 1;
53-
syncLocker();
54-
} else {
55-
lockCount -= 1;
56-
syncLocker();
57-
}
58-
}, [mergedLock]);
59-
60-
const lockRef = React.useRef(mergedLock);
61-
lockRef.current = mergedLock;
62-
63-
useLayoutEffect(() => {
6435
return () => {
65-
if (lockRef.current) {
66-
lockCount -= 1;
67-
syncLocker();
68-
}
36+
removeCSS(id);
6937
};
70-
}, []);
38+
}, [mergedLock, id]);
7139
}

0 commit comments

Comments
 (0)