🔥

巷では useEffect を気軽に使うなと騒がしい、ならいっそ完全に使うのをやめるのはどうだろう?

に公開

よし、こうなったら意地でも useEffect を使わないぞ

前回は fetch を useEffect で使わない記事を書きました。

https://zenn.dev/sora_kumo/articles/next-react-fetch

今回は、ref で拾ったノードに対するイベント処理も useEffect 無しで書いてみます。useSyncExternalStoreの subscribe に実質 useEffect と同等の機能があります。イベントの接続や解除が必要になったら、subscribe のインスタンスを更新すれば、コードが読みやすいかどうかは度外視するとして、同じようなものができあがります。

以下、ノードのサイズ変更を検知して表示するコードです。

https://github.com/SoraKumo001/next-node-event

"use client";
import { useRef, useSyncExternalStore } from "react";

export default function Page() {
  const storeCtx = useRef({
    subscribe: (onStoreChange: () => void) => {
      storeCtx.onStoreChange = onStoreChange;
      return () => {};
    },
    onStoreChange: () => {},
    ref: (node: HTMLDivElement | null) => {
      if (node) {
        storeCtx.subscribe = () => {
          const observer = new ResizeObserver(() => {
            storeCtx.data = {
              width: node.offsetWidth,
              height: node.offsetHeight,
            };
            storeCtx.onStoreChange();
          });
          observer.observe(node);
          return () => observer.disconnect();
        };
        storeCtx.data = {
          width: node.offsetWidth,
          height: node.offsetHeight,
        };
      }
    },
    data: { width: 0, height: 0 },
  }).current;
  const data = useSyncExternalStore(
    storeCtx.subscribe,
    () => storeCtx.data,
    () => storeCtx.data
  );
  return (
    <div className="whitespace-pre" ref={storeCtx.ref}>
      {JSON.stringify(data, null, 4)}
    </div>
  );
}

まとめ

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

上記ドキュメントでも React 外の外部ストアのデータ読み取る場合は useSyncExternalStore が使えると書いてあります。心置きなく useSyncExternalStore に置き換えてください。さあ、今こそ useEffect を使わないコードの世界へ!

炎上、炎上!

GitHubで編集を提案

Discussion