🔥
巷では useEffect を気軽に使うなと騒がしい、ならいっそ完全に使うのをやめるのはどうだろう?
よし、こうなったら意地でも useEffect を使わないぞ
前回は fetch を useEffect で使わない記事を書きました。
今回は、ref で拾ったノードに対するイベント処理も useEffect 無しで書いてみます。useSyncExternalStore
の subscribe に実質 useEffect
と同等の機能があります。イベントの接続や解除が必要になったら、subscribe のインスタンスを更新すれば、コードが読みやすいかどうかは度外視するとして、同じようなものができあがります。
以下、ノードのサイズ変更を検知して表示するコードです。
"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>
);
}
まとめ
上記ドキュメントでも React 外の外部ストアのデータ読み取る場合は useSyncExternalStore
が使えると書いてあります。心置きなく useSyncExternalStore
に置き換えてください。さあ、今こそ useEffect を使わないコードの世界へ!
炎上、炎上!
Discussion