Closed3

useSyncExternalStoreとResizeObserverを使って要素のリサイズ発生時に幅と高さを取得するhooksを作る

m_03m_03

ResizeObserver

  • ブラウザAPI
  • 要素のサイズ変化を監視し、変化するたびに渡したコールバックを実行する
  • 特定の要素のサイズ変更を検知して、その要素が変化した後のパラメータで何か処理を行いたいと時などに使う

div要素のサイズ変更を検知して、divの幅をコンソールに出力するプログラム

...
const [width, setWidth] = useState(0);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
    const observer = new ResizeObserver((entries) => { 
        entries.forEach((entry)=>setWidth(entry.contentRect.width));
     });
    if(ref.current){
        observer.observe(ref.current);
    }
    return () => observer.disconnect();
},[])
// 下記のdivのサイズが変化した時、幅がセットされ再描画が起きるため、widthがコンソールに表示される。
console.log(width)
return <div ref={ref} />

https://developer.mozilla.org/ja/docs/Web/API/Resize_Observer_API

m_03m_03

useSyncExternalStore

  • 外部のデータストアへサブスクライブすることで値を読み取ることができるhooks
  • 可変のブラウザAPIへサブスクライブすることで、値を読み取るなどに使う

ブラウザのネットワークの接続状態が変化するたびに状態を更新して画面を再描画するプログラム

import { useSyncExternalStore } from 'react';

function callback = () => navigator.online;
function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  // サブスクライブ関数の戻り値はイベントに対するリスナーを解除する関数を返す必要がある
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}
const isOnline = useSyncExternalStore(subscribe, callback);

return <div>{isOnline ? "Online" : "Offline"}</div>

https://ja.react.dev/reference/react/useSyncExternalStore

m_03m_03

useSyncExternalStoreとResizeObserverを使って要素のリサイズ発生時に幅と高さを取得するhooks

export const useResizeObserver = <T extends HTMLElement>() => {
  const ref = useRef<T>(null);
  const subscribe = useCallback((onStoreChange: () => void) => {
    const observer = new ResizeObserver((entries) => {
     // 監視対象の要素がリサイズした際、useSyncExternalStoreフックから渡される、
     // 画面の再描画を行う関数を実行する。
      entries.forEach(() => onStoreChange());
    });
    if (ref.current) {
      observer.observe(ref.current);
    }
    return () => observer.disconnect();
  }, []);

  const height = useSyncExternalStore(
    subscribe,
    () => ref.current?.clientHeight || 0
  );
  const width = useSyncExternalStore(
    subscribe,
    () => ref.current?.clientWidth || 0
  );
  return { ref, width, height };
};

SSRを使うアプリの場合

useSyncExternalStoreの第3引数に、サーバーサイドレンダリング時の初期値を返す処理を設定する

このスクラップは2024/04/13にクローズされました