Window Resize イベントで React Component のサイズ取得方法
- なかなかベストプラクティスに落ち着くことができなかったので、メモとして残しておきます。
- 特に、
_.debounce()
でラップしないでうまく実装する方法がなかったのか。 - もっと良い実装があれば、アップデートしていきます。
TL,DR;
-
resize
イベントハンドラー利用します。 -
ref
を通じて、getBoundingClientRect()
でコンポーネントのサイズを取得します。 -
state
にコンポーネントのサイズを格納していきます。 - 無闇やたらとハンドラを呼び出したくないので、Lodash の debounce を使ってます。
- ウィンドウ最大化ボタンのためにも実は debounce は必須。
Hook 形式でも書けるけど、とりあえず Class Component 形式で紹介します。
import React from 'react';
import _ from 'lodash';
class MyComponent extends React.Component {
state = {
size: {
width: 0,
height: 0,
},
};
ref = React.createRef();
handleWindowResize = _.debounce(() => {
const size = this.ref.current.getBoundingClientRect();
this.setState({ size });
});
componentDidMount() {
this.handleWindowResize();
window.addEventListener('resize', this.handleWindowResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleWindowResize);
}
render() {
const { size } = this.state;
return (
<div ref={this.ref}>
Component size is {size.width} x {size.height}.
</div>
);
}
}
Hook API を使った場合の Function Component の実装
import React from 'react';
import _ from 'lodash';
const MyComponent = () => {
const ref = React.useRef(null);
const [size, setSize] = React.useState({
width: 0,
height: 0,
});
const handleWindowResize = _.debounce(() => {
const { width, height } = ref.current.getBoundingClientRect();
setSize({ width, height });
}, 100);
React.useLayoutEffect(() => {
handleWindowResize();
window.addEventListener('resize', handleWindowResize);
return () => window.removeEventListener('resize', handleWindowResize);
});
return (
<div ref={ref}>
Component size is {size.width} x {size.height}.
</div>
);
};