テックタッチアドベントカレンダー17日目を担当する kenshin です。
今年もあと少しで終わりですね。今年を振り返るのために2022年に食べたラーメンの杯数を数えてみると121杯(執筆時点)でした。年末までにあと何杯食べられるかな。
さて、今回は React18 で追加された useSyncExternalStore を使ってみました。
useSyncExternalStore とは
React18 で新たに追加された React フックです。
React コンポーネントの多くは props、state、context からデータを参照します。
ただし、React 外部のデータソースから値を参照する必要がある場合も存在します。
このような場合、 useSyncExternalStore を使うことによって、 React 外部のデータソースのストアを監視し、ストアの値を参照できます。
利用場面
React Docs BETAに、 useSyncExternalStore をどのような場面で利用すればよいかが記載されていました。
①React の外部で状態を管理するライブラリを開発するとき(ライブラリ製作者向け)
②ブラウザーのイベント API をサブスクライブするとき
基本的には useState、useReducer (または状態管理ライブラリ)を使って状態管理すべきで、もし上記ケースに該当する場合は useSyncExternalStore の利用を検討してみてもよいのかもしれません。
使い方
コンポーネントのトップレベルで、 useSyncExternalStore を呼び出します。
useSyncExternalStore の引数には、ストアが変更されるたびに呼び出されるコールバックを登録するための subscribe 関数、ストアの現在の値を返す getSnapshot 関数、そしてオプションで getServerSnapshot を渡します。
getServerSnapshot はサーバーレンダリング時にスナップショットを返すための関数です。
import { useSyncExternalStore } from 'react' import { subscribe, getSnapshot, getServerSnapshot } from './externalStore.js' function ExternalStore() { const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?) // snapshot: ストアの値 // subscribe: ストアが変更されるたびに呼び出されるコールバックを登録するための関数 // getSnapshot: ストアの現在の値を返す関数 // getServerSnapshot: サーバーレンダリング時にスナップショットを返すための関数 // ... }
実際に使ってみよう
今回は利用場面②ブラウザーのイベント API をサブスクライブするケースで、 resize イベントを監視し、ビューポートの幅を取得してみたいと思います。
まず、 resize イベントをサブスクライブする subscribe 関数とビューポートの幅を返す getSnapshot 関数を用意します。
getSnapshot 関数は、 window.innerWidth から取得した値を返します。
subscribe 関数は、引数の callback をイベントリスナーに登録し、登録したイベントリスナーをクリーンアップする関数を返します。
const getSnapshot = () => { return window.innerWidth; }; const subscribe = (callback) => { window.addEventListener("resize", callback); return () => window.removeEventListener("resize", callback); };
用意した2つの関数(subscribe、getSnapshot)を useSyncExternalStore の引数に渡すことで、 window.innerWidth の値を読み取り、変更をサブスクライブできます。
const ViewportWidth = () => { const snapshot = useSyncExternalStore(subscribe, getSnapshot); return ( <div>{snapshot}</div> ); }
実際にビューポートの幅を変更してみると、snapshot の値が変わっているのがわかります。
最後に
今回は React18 で追加された useSyncExternalStore を試してみました。
useSyncExternalStore を使うことで、React コンポーネント内で外部の変更をサブスクライブし、値を参照できました。
今回は、ブラウザのイベント API をサブスクライブするところまでしか試せていませんが、今後は useSyncExternalStore を使って、簡易な状態管理ライブラリも実装してみたいです。
最後まで読んでいただきありがとうございました。