matsutoba’s blog

フロントエンドエンジニアをしています

scrollHeightの変更を検出したい

あるdiv要素の中身が動的に変更されるとき、そのdiv要素のscrollHeightの値を取得したい。

ResizeObserverを使う場合

divのサイズ変更のタイミングで通知してほしい場合はResizeObserverで良さそう。

import React, { useEffect, useState, useRef } from "react";
import styled from "styled-components";

const Wrapper = styled.div`
  width: 200px;
  height: 200px;
  overflow: auto;
`;

export default function App() {
  const ref = useRef<HTMLDivElement>(null);
  const [list, setList] = useState<string[]>([]);

 /* イベント処理 - ここから */
  const callback = (e: ResizeObserverEntry[]) => {
    console.log("Resize", ref.current?.scrollHeight);
  }

  useEffect(() => {
    console.log("MOUNT");
    if (!ref.current) return;
    const observer = new ResizeObserver(callback);
    observer.observe(ref.current);
    return () => {
      observer.disconnect();
    }
  }, [ref]);
 /* イベント処理 - ここまで */

  const onClickAdd = () => {
    setList((list) => [...list, `${list.length}`]);
  };

  const onClickDelete = () => { 
    setList(list => list.slice(1));
  };

  return (
    <div >
      <button onClick={onClickAdd}>add</button>
      <button onClick={onClickDelete}>delete</button>
      <Wrapper>
        <div ref={ref}> {/* このdiv要素のheightを監視 */}
          {list.map((item, index) => {
            return <p key={index}>{item}</p>;
          })}
        </div>
      </Wrapper>
    </div>
  );
}

MutationObserverを使う場合

監視対象の子要素が変化したタイミングでscrollHeightを確認したい場合は、MutationObserverも使えそう。

  /* イベント処理部分を置き換え */

  const callback = (e: MutationRecord[]) => {
    console.log("Resize", ref.current?.scrollHeight);
  }

  useEffect(() => {
    console.log("MOUNT");
    if (!ref.current) return;
    const observer = new MutationObserver(callback);
    observer.observe(ref.current, {attributes:true, childList:true});
    return () => {
      observer.disconnect();
    }
  }, [ref]);