Skip to content

Commit 4f70824

Browse files
authored
refactor: Dialog use rc-portal component instead (#294)
* chore: install portal * test: Fix test case * chore: clean up
1 parent 2644f19 commit 4f70824

File tree

8 files changed

+87
-98
lines changed

8 files changed

+87
-98
lines changed

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module.exports = {
22
setupFiles: ["./tests/setup.js"],
3+
setupFilesAfterEnv: ["./tests/setupFilesAfterEnv.ts"],
34
snapshotSerializers: [require.resolve("enzyme-to-json/serializer")],
45
};

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@
4747
},
4848
"dependencies": {
4949
"@babel/runtime": "^7.10.1",
50+
"@rc-component/portal": "^1.0.0-8",
5051
"classnames": "^2.2.6",
5152
"rc-motion": "^2.3.0",
5253
"rc-util": "^5.21.0"
5354
},
5455
"devDependencies": {
56+
"@testing-library/jest-dom": "^5.16.5",
57+
"@testing-library/react": "^12.0.0",
5558
"@types/enzyme": "^3.10.7",
5659
"@types/jest": "^26.0.14",
5760
"@types/react": "^16.9.2",

src/Dialog/Content/Panel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React, { useRef } from 'react';
22
import classNames from 'classnames';
3-
import type { IDialogChildProps } from '..';
43
import MemoChildren from './MemoChildren';
4+
import type { IDialogPropTypes } from '../../IDialogPropTypes';
55

66
const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' };
77

8-
export interface PanelProps extends Omit<IDialogChildProps, 'getOpenCount'> {
8+
export interface PanelProps extends Omit<IDialogPropTypes, 'getOpenCount'> {
99
prefixCls: string;
1010
ariaId?: string;
1111
onMouseDown?: React.MouseEventHandler;

src/Dialog/index.tsx

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,20 @@ import KeyCode from 'rc-util/lib/KeyCode';
55
import useId from 'rc-util/lib/hooks/useId';
66
import contains from 'rc-util/lib/Dom/contains';
77
import pickAttrs from 'rc-util/lib/pickAttrs';
8-
import type ScollLocker from 'rc-util/lib/Dom/scrollLocker';
98
import type { IDialogPropTypes } from '../IDialogPropTypes';
109
import Mask from './Mask';
1110
import { getMotionName } from '../util';
1211
import Content from './Content';
1312
import type { ContentRef } from './Content/Panel';
1413

15-
export type IDialogChildProps = {
16-
// zombieJ: This should be handle on top instead of each Dialog.
17-
// TODO: refactor to remove this.
18-
getOpenCount: () => number;
19-
scrollLocker?: ScollLocker;
20-
} & IDialogPropTypes;
21-
22-
export default function Dialog(props: IDialogChildProps) {
14+
export default function Dialog(props: IDialogPropTypes) {
2315
const {
2416
prefixCls = 'rc-dialog',
2517
zIndex,
2618
visible = false,
2719
keyboard = true,
2820
focusTriggerAfterClose = true,
29-
scrollLocker,
21+
// scrollLocker,
3022

3123
// Wrapper
3224
wrapStyle,
@@ -151,13 +143,13 @@ export default function Dialog(props: IDialogChildProps) {
151143
[],
152144
);
153145

154-
useEffect(() => {
155-
if (animatedVisible) {
156-
scrollLocker?.lock();
157-
return scrollLocker?.unLock;
158-
}
159-
return () => {};
160-
}, [animatedVisible, scrollLocker]);
146+
// useEffect(() => {
147+
// if (animatedVisible) {
148+
// scrollLocker?.lock();
149+
// return scrollLocker?.unLock;
150+
// }
151+
// return () => {};
152+
// }, [animatedVisible, scrollLocker]);
161153

162154
// ========================= Render =========================
163155
return (

src/DialogWrap.tsx

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
2-
import Portal from 'rc-util/lib/PortalWrapper';
3-
import type { IDialogChildProps } from './Dialog';
2+
import Portal from '@rc-component/portal';
43
import Dialog from './Dialog';
54
import type { IDialogPropTypes } from './IDialogPropTypes';
65

@@ -23,34 +22,36 @@ const DialogWrap: React.FC<IDialogPropTypes> = (props: IDialogPropTypes) => {
2322
}
2423
}, [visible]);
2524

26-
// 渲染在当前 dom 里;
27-
if (getContainer === false) {
28-
return (
29-
<Dialog
30-
{...props}
31-
getOpenCount={() => 2} // 不对 body 做任何操作。。
32-
/>
33-
);
34-
}
25+
// // 渲染在当前 dom 里;
26+
// if (getContainer === false) {
27+
// return (
28+
// <Dialog
29+
// {...props}
30+
// getOpenCount={() => 2} // 不对 body 做任何操作。。
31+
// />
32+
// );
33+
// }
3534

3635
// Destroy on close will remove wrapped div
3736
if (!forceRender && destroyOnClose && !animatedVisible) {
3837
return null;
3938
}
4039

4140
return (
42-
<Portal visible={visible} forceRender={forceRender} getContainer={getContainer}>
43-
{(childProps: IDialogChildProps) => (
44-
<Dialog
45-
{...props}
46-
destroyOnClose={destroyOnClose}
47-
afterClose={() => {
48-
afterClose?.();
49-
setAnimatedVisible(false);
50-
}}
51-
{...childProps}
52-
/>
53-
)}
41+
<Portal
42+
open={visible || forceRender || animatedVisible}
43+
autoDestroy={false}
44+
getContainer={getContainer}
45+
autoLock={visible || animatedVisible}
46+
>
47+
<Dialog
48+
{...props}
49+
destroyOnClose={destroyOnClose}
50+
afterClose={() => {
51+
afterClose?.();
52+
setAnimatedVisible(false);
53+
}}
54+
/>
5455
</Portal>
5556
);
5657
};

tests/index.spec.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */
22
import React, { cloneElement } from 'react';
33
import { act } from 'react-dom/test-utils';
4+
import { render } from '@testing-library/react';
45
import type { ReactWrapper } from 'enzyme';
56
import { mount } from 'enzyme';
6-
import Portal from 'rc-util/lib/Portal';
77
import KeyCode from 'rc-util/lib/KeyCode';
88
import type { DialogProps } from '../src';
99
import Dialog from '../src';
@@ -295,23 +295,24 @@ describe('dialog', () => {
295295

296296
describe('getContainer is false', () => {
297297
it('not set', () => {
298-
const wrapper = mount(
298+
const { container } = render(
299299
<Dialog visible>
300-
<div>forceRender element</div>
300+
<div className="bamboo" />
301301
</Dialog>,
302302
);
303-
expect(wrapper.find('.rc-dialog-body > div').text()).toEqual('forceRender element');
304-
expect(wrapper.find(Portal)).toHaveLength(1);
303+
304+
expect(container.querySelector('.bamboo')).toBeFalsy();
305+
expect(document.body.querySelector('.bamboo')).toBeTruthy();
305306
});
306307

307308
it('set to false', () => {
308-
const wrapper = mount(
309+
const { container } = render(
309310
<Dialog visible getContainer={false}>
310-
<div>forceRender element</div>
311+
<div className="bamboo" />
311312
</Dialog>,
312313
);
313-
expect(wrapper.find('.rc-dialog-body > div').text()).toEqual('forceRender element');
314-
expect(wrapper.find(Portal)).toHaveLength(0);
314+
315+
expect(container.querySelector('.bamboo')).toBeTruthy();
315316
});
316317
});
317318

tests/scroll.spec.tsx

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */
22
import React from 'react';
3-
import { mount } from 'enzyme';
3+
import { render } from '@testing-library/react';
44
import Dialog from '../src';
55

66
/**
@@ -17,75 +17,65 @@ describe('Dialog.Scroll', () => {
1717
});
1818

1919
it('Single Dialog body overflow set correctly', () => {
20-
const wrapper = mount(<Dialog />, { attachTo: document.body });
21-
document.body.style.overflow = 'scroll';
20+
const { unmount, rerender } = render(<Dialog visible />);
2221

23-
wrapper.setProps({ visible: true });
24-
jest.runAllTimers();
25-
wrapper.update();
26-
expect(document.body.style.overflow).toBe('hidden');
22+
expect(document.body).toHaveStyle({
23+
overflowY: 'hidden',
24+
});
2725

28-
wrapper.setProps({ visible: false });
29-
jest.runAllTimers();
30-
wrapper.update();
31-
expect(document.body.style.overflow).toBe('scroll');
26+
rerender(<Dialog />);
27+
expect(document.body).not.toHaveStyle({
28+
overflowY: 'hidden',
29+
});
3230

33-
wrapper.unmount();
31+
// wrapper.unmount();
32+
unmount();
3433
});
3534

3635
it('Multiple Dialog body overflow set correctly', () => {
37-
document.body.style.overflow = 'scroll';
38-
3936
const Demo = ({ visible = false, visible2 = false, ...restProps }) => (
4037
<div>
4138
<Dialog {...restProps} visible={visible} />
4239
<Dialog {...restProps} visible={visible2} />
4340
</div>
4441
);
4542

46-
const wrapper = mount(<Demo />, { attachTo: document.body });
47-
48-
expect(wrapper.find('.rc-dialog').length).toBe(0);
49-
50-
wrapper.setProps({ visible: true });
51-
jest.runAllTimers();
43+
const { rerender, unmount } = render(<Demo />);
5244

53-
expect(wrapper.find('div.rc-dialog').length).toBe(1);
54-
expect(document.body.style.overflow).toBe('hidden');
45+
expect(document.querySelector('.rc-dialog')).toBeFalsy();
5546

56-
wrapper.setProps({ visible2: true });
57-
jest.runAllTimers();
58-
59-
expect(wrapper.find('div.rc-dialog').length).toBe(2);
60-
expect(document.body.style.overflow).toBe('hidden');
47+
rerender(<Demo visible />);
48+
expect(document.querySelectorAll('.rc-dialog')).toHaveLength(1);
49+
expect(document.body).toHaveStyle({
50+
overflowY: 'hidden',
51+
});
6152

62-
wrapper.setProps({
63-
visible: false,
64-
visible2: false,
53+
rerender(<Demo visible visible2 />);
54+
expect(document.querySelectorAll('.rc-dialog')).toHaveLength(2);
55+
expect(document.body).toHaveStyle({
56+
overflowY: 'hidden',
6557
});
66-
jest.runAllTimers();
6758

68-
expect(document.body.style.overflow).toBe('scroll');
59+
rerender(<Demo />);
60+
expect(document.body).not.toHaveStyle({
61+
overflowY: 'hidden',
62+
});
6963

70-
wrapper.setProps({
71-
visible: true,
64+
rerender(<Demo visible />);
65+
expect(document.body).toHaveStyle({
66+
overflowY: 'hidden',
7267
});
73-
jest.runAllTimers();
74-
expect(document.body.style.overflow).toBe('hidden');
7568

76-
wrapper.setProps({
77-
visible: false,
78-
visible2: true,
69+
rerender(<Demo visible2 />);
70+
expect(document.body).toHaveStyle({
71+
overflowY: 'hidden',
7972
});
80-
jest.runAllTimers();
81-
expect(document.body.style.overflow).toBe('hidden');
8273

83-
wrapper.setProps({
84-
visible: false,
85-
visible2: false,
74+
rerender(<Demo />);
75+
expect(document.body).not.toHaveStyle({
76+
overflowY: 'hidden',
8677
});
87-
jest.runAllTimers();
88-
expect(document.body.style.overflow).toBe('scroll');
89-
wrapper.unmount();
78+
79+
unmount();
9080
});
9181
});

tests/setupFilesAfterEnv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import '@testing-library/jest-dom';

0 commit comments

Comments
 (0)