417 文字
2 分
useEffectEventについてのメモ
イベントとエフェクタの分離が useEffectEvent の目的、useEvent の後継として提案されている。
2024 年 1 月時点では、experimental、canary にも入っていない。
https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event
次のようなカスタムフックを考える。
function useChatRoom({ roomId, theme }) { useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.on("connected", () => { showNotification("Connected!", theme); }); connection.connect(); return () => { connection.disconnect(); }; }, [roomId, theme]);}
この例では、theme が切り替わる度に ChatRoom への接続が切れてしまう。ただし theme はリアクティブな値であるため、依存関係から入れる必要がある。
useEffectEvent を使えばリアクティブにしたくないイベントを、エフェクトから分離することが出来る。roomId の変更によってのみ再接続が行われる。
function useChatRoom({ roomId, theme }) { const onConnected = useEffectEvent(() => { showNotification("Connected!", theme); });
useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.on("connected", () => { onConnected(); }); connection.connect(); return () => connection.disconnect(); }, [roomId]);}
制約
- エフェクト内からのみ呼び出せる。
- 他のコンポーネントやフックには渡せない。
const onTick = useEffectEvent(() => { callback();});
// これはダメuseTimer(onTick)
<Timer // これはダメ onTick={onTick}/>
useEffectEvent を利用した例
Callback が変更されても、interval がリセットされない。useEffectEvent を利用しない場合、callback が変更された際に interval がリセットされる。
function useTimer(callback, delay) { const onTick = useEffectEvent(() => { callback(); });
useEffect(() => { const id = setInterval(() => { onTick(); }, delay); return () => { clearInterval(id); }; }, [delay]);}
URL が変更されたときのみログを出せる。useEffectEvent を利用しない場合、items が変更された場合にもログが出てしまう。
function Page({ url }) { const { items } = useContext(ShoppingCartContext); const numberOfItems = items.length;
const onVisit = useEffectEvent((visitedUrl) => { logVisit(visitedUrl, numberOfItems); });
useEffect(() => { onVisit(url); }, [url]);}
useEffectEventについてのメモ
https://blog.ohirunewani.com/posts/use-effect-event-memo/