Skip to content

Commit 6fc5c55

Browse files
Refactor/resize (#324)
* refactor: add custom element observe * test: supply Resize unit test * docs: supply Resize component demos
1 parent a182493 commit 6fc5c55

File tree

5 files changed

+122
-87
lines changed

5 files changed

+122
-87
lines changed
Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,52 @@
11
import React from 'react';
22
import Resize from '../index';
3-
import { render, cleanup, fireEvent } from '@testing-library/react';
3+
import { render, fireEvent } from '@testing-library/react';
44
import '@testing-library/jest-dom/extend-expect';
55

6-
class Component extends React.PureComponent {
7-
state = {
8-
count: 0,
9-
};
10-
render() {
11-
const { count } = this.state;
12-
return (
13-
<Resize onResize={() => this.setState({ count: count + 1 })}>
14-
<div
15-
data-testid="test"
16-
style={{
17-
height: '240px',
18-
width: '100%',
19-
}}
20-
>
21-
{count}
22-
</div>
23-
</Resize>
24-
);
25-
}
26-
}
27-
28-
describe('test Resize', () => {
29-
let wrapper: any, element: any;
6+
describe('Resize', () => {
7+
let originalResizeObserver: typeof global.ResizeObserver;
308
beforeEach(() => {
31-
wrapper = render(<Component />);
32-
element = wrapper.getByTestId('test');
9+
originalResizeObserver = global.ResizeObserver;
10+
global.ResizeObserver = class {
11+
callback: any;
12+
constructor(callback: any) {
13+
this.callback = callback;
14+
}
15+
observe() {
16+
this.callback();
17+
}
18+
unobserve() {}
19+
disconnect() {}
20+
};
3321
});
22+
3423
afterEach(() => {
35-
cleanup();
24+
global.ResizeObserver = originalResizeObserver;
3625
});
37-
test('should calculate current width', () => {
38-
expect(element.firstChild).toMatchInlineSnapshot('0');
26+
27+
test('should render children', () => {
28+
const { getByText } = render(<Resize>test</Resize>);
29+
expect(getByText('test')).toBeInTheDocument();
30+
});
31+
32+
test('should add resize event listener to window if observerEle is not provided', () => {
33+
const onResize = jest.fn();
34+
const { unmount } = render(<Resize onResize={onResize} />);
3935
fireEvent(window, new Event('resize'));
40-
expect(element.firstChild).toMatchInlineSnapshot('1');
36+
37+
expect(onResize).toBeCalledTimes(1);
38+
unmount();
39+
});
40+
41+
test('should add resize observer to observerEle if observerEle is provided', () => {
42+
const onResize = jest.fn();
43+
const observerEle = document.createElement('div');
44+
const { unmount } = render(<Resize onResize={onResize} observerEle={observerEle} />);
45+
observerEle.style.width = '100px';
46+
observerEle.style.height = '100px';
47+
global.dispatchEvent(new Event('resize'));
48+
49+
expect(onResize).toHaveBeenCalled();
50+
unmount();
4151
});
4252
});

src/resize/demos/basic.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { useState, useCallback } from 'react';
2+
import { Resize } from 'dt-react-component';
3+
4+
export default () => {
5+
const [innerWidth, setInnerWidth] = useState(window.innerWidth);
6+
const [innerHeight, setInnerHeight] = useState(window.innerHeight);
7+
8+
const onResize = useCallback(() => {
9+
setInnerWidth(window.innerWidth);
10+
setInnerHeight(window.innerHeight);
11+
}, []);
12+
13+
return (
14+
<Resize onResize={onResize}>
15+
<div>
16+
<pre>window高度: {innerWidth}</pre>
17+
<pre>window宽度: {innerHeight}</pre>
18+
</div>
19+
</Resize>
20+
);
21+
};

src/resize/demos/observerEle.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React, { useState, useCallback, useRef } from 'react';
2+
import { Resize } from 'dt-react-component';
3+
4+
export default () => {
5+
const [clientWidth, setWidth] = useState(0);
6+
const [clientHegiht, setHegiht] = useState(0);
7+
const textareaRef = useRef<HTMLTextAreaElement>(null);
8+
9+
const onResize = useCallback(() => {
10+
setWidth(textareaRef.current!.clientWidth);
11+
setHegiht(textareaRef.current!.clientHeight);
12+
}, []);
13+
14+
return (
15+
<Resize onResize={onResize} observerEle={textareaRef.current}>
16+
<textarea
17+
ref={textareaRef}
18+
style={{
19+
resize: 'both',
20+
maxWidth: '100%',
21+
}}
22+
/>
23+
<pre>当前元素的可视宽: {clientWidth}</pre>
24+
<pre>当前元素的可视宽: {clientHegiht}</pre>
25+
</Resize>
26+
);
27+
};

src/resize/index.md

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,23 @@ demo:
88

99
# Resize Resize 事件监听
1010

11+
用于监听 window 或者是其他元素的尺寸变化
12+
1113
## 何时使用
1214

1315
元素大小自适应调整,常用于图表
1416

1517
## 示例
1618

17-
```jsx
18-
/**
19-
* title: "基础使用"
20-
* description: "请调整窗口大小以查看效果"
21-
*/
22-
import React, { useState } from 'react';
23-
import { Resize } from 'dt-react-component';
24-
25-
export default () => {
26-
const [clientWidth, setWidth] = useState(0);
27-
28-
return (
29-
<>
30-
<Resize
31-
onResize={() => {
32-
const box = document.getElementById('box');
33-
setWidth(box.clientWidth);
34-
}}
35-
>
36-
<div
37-
id="box"
38-
style={{
39-
height: '240px',
40-
width: '100%',
41-
padding: '10px',
42-
border: '1px solid rgba(0,0,0,.1)',
43-
}}
44-
>
45-
<pre>width: {clientWidth}</pre>
46-
</div>
47-
</Resize>
48-
</>
49-
);
50-
};
51-
```
19+
<code src="./demos/basic.tsx" description="请调整窗口大小以查看效果">基础使用</code>
20+
<code src="./demos/observerEle.tsx" description="请调整元素大小以查看效果,通过设置`observerEle`自定义监听元素">监听自定义元素</code>
5221

5322
## API
5423

55-
| 参数 | 说明 | 类型 | 默认值 |
56-
| -------- | ------------------ | ----------------- | ------ |
57-
| onResize | 重置元素大小的函数 | `Function` | - |
58-
| children | 子元素 | `React.ReactNode` | - |
24+
### Resize
25+
26+
| 参数 | 说明 | 类型 | 默认值 |
27+
| ----------- | ---------------------------------------- | ----------------- | ------ |
28+
| children | 子元素 | `React.ReactNode` | - |
29+
| observerEle | 监听的元素,传入元素不存在默认监听 window | `HTMLElement` | - |
30+
| onResize | 重置元素大小的函数 | `() => void` | - |

src/resize/index.tsx

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1-
import React from 'react';
1+
import React, { useEffect } from 'react';
22

33
export interface ResizeProps {
4-
onResize?: Function;
4+
observerEle?: HTMLElement | null;
55
children?: React.ReactNode;
6+
onResize?: () => void;
67
}
7-
export default class Resize extends React.Component<ResizeProps, any> {
8-
componentDidMount() {
9-
window.addEventListener('resize', this.resize, false);
10-
}
118

12-
componentWillUnmount() {
13-
window.removeEventListener('resize', this.resize, false);
14-
}
9+
const Resize: React.FC<ResizeProps> = ({ observerEle, onResize, children }) => {
10+
useEffect(() => {
11+
if (typeof onResize !== 'function') return;
12+
if (!observerEle) {
13+
window.addEventListener('resize', onResize, false);
14+
return () => {
15+
window.removeEventListener('resize', onResize, false);
16+
};
17+
} else {
18+
const resizeObserver = new ResizeObserver(onResize);
19+
resizeObserver.observe(observerEle);
20+
return () => {
21+
resizeObserver.unobserve(observerEle);
22+
};
23+
}
24+
}, [onResize, observerEle]);
1525

16-
resize = () => {
17-
const { onResize } = this.props;
18-
if (onResize) onResize();
19-
};
26+
return <>{children}</>;
27+
};
2028

21-
render() {
22-
return this.props.children;
23-
}
24-
}
29+
export default Resize;

0 commit comments

Comments
 (0)