【React状態管理】Zustandでストアを複数コンポーネントで使い回す
はじめに
状態管理ライブラリを使用していて、ストア(状態とアクションのセット)を複数コンポーネントで使い回したい!
ということはありませんか?
この記事では Zustand という React の状態管理ライブラリを使用して、同じストアを複数コンポーネントで使いまわす例を紹介します。
Zustand とは
こちらの記事がとてもわかりやすいです。感謝。
Zustand は、React Developer ロードマップ でも 2023 年 2 月現在、推奨の状態管理ライブラリとして指定されています。
バージョン情報
基本形
ボタンをクリックすると、カウンターがインクリメントされるというシンプルなサンプルです。
シンプルなストアの実装です。
複数 NG パターン
次に NG パターンを見てみましょう。
ボタンをクリックすると、両方の数値がインクリメントされてしまいます。
同一のストアを参照しているからです。
複数 OK パターン
そして、複数のコンポーネントの状態を独立して管理できている OK パターンです。
ストアを生成するのではなく、ストアを生成する関数式を定義しています。
そして、コンテキストとプロバイダを定義します。
プロバイダの中でストアを生成している点にご注目ください。
それぞれのカウンターにプロバイダでストアを供給しています。
このようにして、独立したストアを提供している訳です。
subscribe
OK パターンでは subscribe メソッドを呼び出すことができません。
subscribe メソッドを呼び出せるように追加の実装が必要です。
StoreApi 型のストアを取得するメソッドを追加します。
subscribe メソッドを呼び出せるようになりました。
ボタンをクリックするとコンソールにログ出力します。
Redux Devtools
Zustand では Redux Devtools を使用して、状態を追跡することが可能です。
devtools メソッドを実装します。
Redeux DevTool で確認すると、異なるストアで状態管理していることを確認できます。
残念ながら codesandbox 上では正常に動作しないようなので、ここではソースコードの改修箇所のご紹介に留めておきます。
まとめ
ストア(ステートとアクションのセット)を使いまわしたい。
きっと、誰でも一度はそう思いますよね(?)
機能として提供されていても良さそうなのですが、ドキュメントのどこにもそのような記述を見つけることができませんでした。
Redux など他の状態管理ツールや issue なども調査しました。
同様の問題を抱えている開発者は少なくありませんでした。
しかし、Zustand を除くライブラリ開発サイドからの回答では、「配列を使え」とか「マップにしてキー管理するように」などのベタな回答しか見つけることができませんでした。
ところが、Zustand の issue にて、今回の記事でご紹介したようなサンプルを見つけることができました。
サンプルコードを提示してくださっていたのは Jotai 開発者でもあられる daishi さんです。
今回の記事ではそのサンプルを元に、TypeScript に置き換え、型の定義を明確にし、全体的に整理をしました。
さらに、devtools の実装方法も追加しました。
尚、この例ではコンテキストとプロバイダを使用していますが、一般的にはコンテキストやプロバイダは使用しません。
今回は複数コンポーネントで使いまわしたいという目的だったので、コンテキストとプロバイダを使用しています。
Zustand を使っていて、プロバイダが積み重なる・・・ということには通常ならないのでご安心ください。
サンプルコードを提示してくださった daishi さんに心から感謝致します。
参考資料
Discussion