Skip to content

Commit 0b48d3d

Browse files
committed
feat: drawerwrapper function
1 parent dba1423 commit 0b48d3d

File tree

3 files changed

+103
-130
lines changed

3 files changed

+103
-130
lines changed

docs/examples/base.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const Demo = () => {
1818
<Drawer
1919
onChange={onChange}
2020
open={open}
21+
// defaultOpen
2122
onClose={onTouchEnd}
2223
handler={false}
2324
level={null}

src/DrawerWrapper.tsx

Lines changed: 98 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,127 @@
1+
import omit from 'rc-util/lib/omit';
12
import Portal from 'rc-util/lib/PortalWrapper';
2-
import * as React from 'react';
3+
import React, { useEffect, useRef, useState } from 'react';
34

45
import Child from './DrawerChild';
56
import type { IDrawerProps, IDrawerChildProps } from './IDrawerPropTypes';
67

7-
interface IState {
8-
open: boolean;
9-
}
10-
118
interface IChildProps extends IDrawerChildProps {
129
visible?: boolean;
1310
afterClose?: () => void;
1411
}
15-
class DrawerWrapper extends React.Component<IDrawerProps, IState> {
16-
public static defaultProps = {
17-
prefixCls: 'drawer',
18-
placement: 'left',
19-
getContainer: 'body',
20-
defaultOpen: false,
21-
level: 'all',
22-
duration: '.3s',
23-
ease: 'cubic-bezier(0.78, 0.14, 0.15, 0.86)',
24-
onChange: () => {},
25-
afterVisibleChange: () => {},
26-
handler: (
27-
<div className="drawer-handle">
28-
<i className="drawer-handle-icon" />
29-
</div>
30-
),
31-
showMask: true,
32-
maskClosable: true,
33-
maskStyle: {},
34-
wrapperClassName: '',
35-
className: '',
36-
keyboard: true,
37-
forceRender: false,
38-
autoFocus: true,
39-
};
12+
const defaultProps: IDrawerProps = {
13+
prefixCls: 'drawer',
14+
placement: 'left',
15+
getContainer: 'body',
16+
defaultOpen: false,
17+
level: 'all',
18+
duration: '.3s',
19+
ease: 'cubic-bezier(0.78, 0.14, 0.15, 0.86)',
20+
onChange: () => {},
21+
afterVisibleChange: () => {},
22+
handler: (
23+
<div className="drawer-handle">
24+
<i className="drawer-handle-icon" />
25+
</div>
26+
),
27+
showMask: true,
28+
maskClosable: true,
29+
maskStyle: {},
30+
wrapperClassName: '',
31+
className: '',
32+
keyboard: true,
33+
forceRender: false,
34+
autoFocus: true,
35+
};
36+
const DrawerWrapper = (props: IDrawerProps) => {
37+
const {
38+
getContainer = defaultProps.getContainer,
39+
handler = defaultProps.handler,
40+
wrapperClassName = defaultProps.wrapperClassName,
41+
forceRender = defaultProps.forceRender,
42+
defaultOpen = defaultProps.defaultOpen,
43+
afterVisibleChange = defaultProps.afterVisibleChange,
44+
onHandleClick,
45+
onClose,
46+
open: propOpen,
47+
} = props;
48+
const hasDefaultOpen = 'defaultOpen' in props;
49+
const [open, setOpen] = useState(defaultOpen);
4050

41-
public static getDerivedStateFromProps(
42-
props: IDrawerProps,
43-
{ prevProps }: { prevProps: IDrawerProps },
44-
) {
45-
const newState: {
46-
open?: boolean;
47-
prevProps: IDrawerProps;
48-
} = {
49-
prevProps: props,
50-
};
51-
if (typeof prevProps !== 'undefined' && props.open !== prevProps.open) {
52-
newState.open = props.open;
51+
useEffect(() => {
52+
if (!hasDefaultOpen) {
53+
setOpen(propOpen);
5354
}
54-
return newState;
55-
}
56-
57-
public dom: HTMLElement | null;
55+
}, [hasDefaultOpen, propOpen]);
5856

59-
constructor(props: IDrawerProps) {
60-
super(props);
61-
const open =
62-
typeof props.open !== 'undefined' ? props.open : !!props.defaultOpen;
63-
this.state = {
64-
open,
65-
};
66-
if ('onMaskClick' in props) {
67-
console.warn('`onMaskClick` are removed, please use `onClose` instead.');
68-
}
57+
if ('onMaskClick' in props) {
58+
console.warn('`onMaskClick` are removed, please use `onClose` instead.');
6959
}
7060

71-
private onHandleClick = (e: React.MouseEvent | React.KeyboardEvent) => {
72-
const { onHandleClick, open: $open } = this.props;
61+
const dom = useRef<HTMLDivElement>(null);
62+
63+
const handleClick = (e: React.MouseEvent | React.KeyboardEvent) => {
7364
if (onHandleClick) {
7465
onHandleClick(e);
7566
}
76-
if (typeof $open === 'undefined') {
77-
const { open } = this.state;
78-
this.setState({
79-
open: !open,
80-
});
81-
}
67+
setOpen(c => !c);
8268
};
8369

84-
private onClose = (e: React.MouseEvent | React.KeyboardEvent) => {
85-
const { onClose, open } = this.props;
70+
const handleOnClose = (e: React.MouseEvent | React.KeyboardEvent) => {
8671
if (onClose) {
8772
onClose(e);
8873
}
89-
if (typeof open === 'undefined') {
90-
this.setState({
91-
open: false,
92-
});
93-
}
74+
setOpen(false);
9475
};
76+
const childProps = omit({ ...defaultProps, ...props }, [
77+
'defaultOpen',
78+
'getContainer',
79+
'wrapperClassName',
80+
'forceRender',
81+
'handler',
82+
]);
9583

96-
// tslint:disable-next-line:member-ordering
97-
public render() {
98-
const {
99-
defaultOpen,
100-
getContainer,
101-
wrapperClassName,
102-
forceRender,
103-
handler,
104-
...props
105-
} = this.props;
106-
const { open } = this.state;
107-
// 渲染在当前 dom 里;
108-
if (!getContainer) {
109-
return (
110-
<div
111-
className={wrapperClassName}
112-
ref={c => {
113-
this.dom = c;
114-
}}
115-
>
116-
<Child
117-
{...props}
118-
open={open}
119-
handler={handler}
120-
getContainer={() => this.dom as HTMLElement}
121-
onClose={this.onClose}
122-
onHandleClick={this.onHandleClick}
123-
/>
124-
</div>
125-
);
126-
}
127-
// 如果有 handler 为内置强制渲染;
128-
const $forceRender = !!handler || forceRender;
129-
84+
// 渲染在当前 dom 里;
85+
if (!getContainer) {
13086
return (
131-
<Portal
132-
visible={open}
133-
forceRender={$forceRender}
134-
getContainer={getContainer}
135-
wrapperClassName={wrapperClassName}
136-
>
137-
{({ visible, afterClose, ...rest }: IChildProps) => (
138-
// react 15,componentWillUnmount 时 Portal 返回 afterClose, visible.
139-
<Child
140-
{...props}
141-
{...rest}
142-
open={visible !== undefined ? visible : open}
143-
afterVisibleChange={
144-
afterClose !== undefined ? afterClose : props.afterVisibleChange
145-
}
146-
handler={handler}
147-
onClose={this.onClose}
148-
onHandleClick={this.onHandleClick}
149-
/>
150-
)}
151-
</Portal>
87+
<div className={wrapperClassName} ref={dom}>
88+
<Child
89+
{...childProps}
90+
open={open}
91+
handler={handler}
92+
getContainer={() => dom.current as HTMLElement}
93+
onClose={handleOnClose}
94+
onHandleClick={handleClick}
95+
/>
96+
</div>
15297
);
15398
}
154-
}
99+
// 如果有 handler 为内置强制渲染;
100+
const $forceRender = !!handler || forceRender;
101+
102+
return (
103+
<Portal
104+
visible={open}
105+
forceRender={$forceRender}
106+
getContainer={getContainer}
107+
wrapperClassName={wrapperClassName}
108+
>
109+
{({ visible, afterClose, ...rest }: IChildProps) => (
110+
// react 15,componentWillUnmount 时 Portal 返回 afterClose, visible.
111+
<Child
112+
{...childProps}
113+
{...rest}
114+
open={visible !== undefined ? visible : open}
115+
afterVisibleChange={
116+
afterClose !== undefined ? afterClose : afterVisibleChange
117+
}
118+
handler={handler}
119+
onClose={handleOnClose}
120+
onHandleClick={handleClick}
121+
/>
122+
)}
123+
</Portal>
124+
);
125+
};
155126

156127
export default DrawerWrapper;

tests/__snapshots__/drawer.spec.tsx.snap

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,14 @@ exports[`Drawer render dom 1`] = `
9898

9999
exports[`Drawer render function 1`] = `
100100
<body
101-
class="ant-scrolling-effect"
102-
style="overflow: hidden; overflow-x: hidden; overflow-y: hidden;"
101+
class=""
102+
style=""
103103
>
104104
<div>
105105
<div>
106106
<div
107-
class="main"
107+
class="main ant-scrolling-effect"
108+
style="overflow: hidden; overflow-x: hidden; overflow-y: hidden;"
108109
>
109110
<div>
110111
<div

0 commit comments

Comments
 (0)