何をするか?
React 用の UI ライブラリである mui(旧: Material-UI)が提供している Snackbar コンポーネント を使うと、次のようなスナックバーを表示することができます。
ただ、MUI はあくまで UI ライブラリなので、表示の制御は React コンポーネントのステート管理の仕組み(useState
など)を使って自力で行わなければいけません。
ただメッセージを表示したいだけなのに、ステート管理とか面倒です。
ここでは、MUI のスナックバーを簡単に表示できるようなフック関数 (useSnackbar
) を作成してみます。
使い方のイメージは次のような感じです。
任意の React コンポーネント(あるいは Next.js のページ)から、上記のように useSnackbar
フック関数を呼び出して、返された showSnackbar
関数を呼び出すだけです。
なお、以下の実装では React のコンテキストの仕組み(グローバル変数的なもの)をふんだんに利用しているので、そのあたりは下記記事を参考にすると理解しやすいと思います。
スナックバー用の UI コンポーネントの作成
まずはスナックバーを表示するための UI コンポーネントを作成しておきます。
コンポーネント名は MUI の Snackbar
と被らないように、GlobalSnackbar
としました(AppSnackbar
でもいいかも)。
実装はほぼ MUI の Snackbar ドキュメント からの流用ですが、props で onClose
ハンドラの登録や、色の指定を行えるようにしています。
スナックバーは 6 秒放置で自動クローズするようにしていますが、このあたりは props でカスタマイズできるようにしておいてもいいかもしれません。
表示位置は anchorOrigin
prop で柔軟に制御できますが、ここはアプリ内で統一されていた方がよいので、props に切り出す必要はありません。
コンテキストおよびフック関数の実装
今回のキモとなるコンテキストオブジェクトの定義です。
SnackbarContext
というコンテキストオブジェクトを定義して、スナックバーに表示すべき内容をグローバルに管理します。
コンテキストオブジェクトには、showSnackbar
という関数も持たせるようにして、どの階層のコンポーネントからでもスナックバーを表示できるようにしています。
ここでは、コンテキストオブジェクトの Provider コンポーネント (SnackbarContext.Provider
) の下に、スナックバーの UI コンポーネント (GlobalSnackbar
) も配置しちゃってます。
ちょっと行儀悪いかもしれませんが、このコンポーネントを使う側で楽をしたかったので。
アプリの上位にコンテキストオブジェクトの Provider を配置
作成した SnackbarContextProvider
は、その子コンポーネントに対してスナックバー用のコンテキストオブジェクト (SnackbarContext
) を提供します。
具体的には、スナックバーの表示状態や、表示トリガーとなる関数です。
この Provider クラスは、コンポーネント階層の上の方に配置しておきます。
Next.js であれば、pages/_app.tsx
あたりでしょうか。
これで、任意のコンポーネントから showSnackbar
関数を呼び出せるようになります。
// ...(省略)...
const SamplePage: NextPage = () => {
const { showSnackbar } = useSnackbar()
return <Button onClick={() => showSnackbar('Success!', 'success')}>Show</Button>
}
関連記事