ツクログ

tsukulognet

tsukulognet

道産子。Reactでなまら面白いものを作りたい。

【React hooks】要素のリサイズを検知して何かをするカスタムフックを作成する

eye catch

useResizeObserver

以下のようにしてuseResizeObserver.jsを作成します。 useResizeObserver.js

import { useEffect } from 'react'

const useResizeObserver = (elements, callback) => {
  useEffect(() => {
    const resizeObserver = new ResizeObserver((entries) => {
      callback(entries);
    });

    for (const elem of elements) {
      elem.current && resizeObserver.observe(elem.current);
    }

    return () => resizeObserver.disconnect();
  }, []);
};

export default useResizeObserver

フックを呼び出す際、仮引数elementsには変更を検知したい要素を配列で入れます。また、仮引数callbackには何らかの処理を行う関数を入れます。

ResizeObserverのobserveメソッドでelements配列内の要素を監視します。監視中に要素のリサイズを検知するとcallback関数が呼び出され、何らかの処理が行われます。

使い方

Appコンポーネント内でuseResizeObserverフックを使うと以下のようになります。

const App = () => {
    const [width, setWidth] = useState(0)

    const element = useRef(null)

    const handleResize = (entries) => {
        const width = entries[0].contentRect.width
        setWidth(Math.floor(width))
    }

  useResizeObserver([element], handleResize);

    const style = {
        backgroundColor: "red",
        height: "40vmin",
        width: "40vmin"
    }

    return (
        <div className="App">
            <div
                ref={element}
                style={style}
            >{width}px</div>
        </div>
    )
}

上記の例では、elementを監視しており、elementのリサイズが検知される度に、リサイズ後のサイズがページ上に表示されます。

handleResize関数では要素の横幅を取得しています。尚、要素のスタイルでwidthとheightの単位をvminとしているため、スクリーンサイズの変化に応じて要素がリサイズされます。

使用例

スクリーンサイズを変化させると要素内の数値(横幅)が変化することが確認できます。