コンポーザブルの依存関係を明確にする方法
コンポーザブルの依存関係を明確にするには、以下の要素が必要です
- コンポーネントから状態とロジックをコンポーサブルに切り出す
-
useState
を使わない -
provide
/inject
を使う - コンポーザブルの引数にコンポーザブルを取る
コンポーネントから状態とロジックをコンポーサブルに切り出す
これはコンポーザブルを使いましょうという話です。
コンポーザブル関数の詳細は公式を参照してください↓
たいてい状態とロジックはセットで存在しています。
Vue3ではSFC内のscriptタグ、templateタグ、styleタグにコーディングを行いコンポーネントを作成しますが、scriptタグ内に書かれている状態とロジックはできる限りコンポーザブルに移行する方が良いと思います。
もちろん状態/ロジックとは言っても、業務に直接関わるドメイン的な状態&ロジックや表示用の状態&ロジックがあるわけですが、そこは別々にコンポーザブルを作成するなどの工夫でより保守性・可読性を高めることができます。
useState
を使わない
これは基本的にグローバルに状態管理をしないということです。
useState
を使うと全てのコンポーサブル/コンポーネントどこからでもアクセス出来てしまいます。どこからでもアクセスできるということは、状態に対する不適切な操作が入り込む隙を生みます。グローバルな状態管理はユーザー情報など最低限に抑えたほうがいいでしょう。
useState
を使わない場合、コンポーザブル内で定義したリアクティブ変数を用いて状態を管理します。
provide
/ inject
を使う
上記の通り、状態管理にコンポーザブル内で定義したリアクティブ変数を使う場合、問題になるのは同じコンポーザブルでも別々の箇所で呼び出したコンポーサブルの状態は当然別ということです。
親コンポーネントで呼び出したコンポーザブルの状態と子コンポーネントで呼び出したコンポーザブルの状態は、同じコンポーザブルを使っていても別物として扱われるため繋がりがありません。この場合、子コンポーネントで状態に対する操作を行なっても、親コンポーネント側の状態は変化しません。
そこでprovide
/ inject
を使います。↓
コンポーザブルの呼び出しは親コンポーネントで行い、それをprovide
を用いて子/孫コンポーネントに公開します。子/孫コンポーネントはinject
でそのコンポーザブルを参照することで、同じコンポーザブルを参照していることになり、状態も共有されます。つまりこの場合、アプリケーション内でコンポーザブルを呼び出すのは1回だけ ということです。
これは特定のコンポーネントツリーの中だけで共有する状態を定義できるということでもあります。
コンポーザブルの引数にコンポーザブルを取る
この点が本記事の肝ですが、コンポーサブルの引数で別のコンポーザブルを受け付けることでコンポーザブルの依存関係を明確に出来ます。これは同時に状態の関係性が明確になるということでもあります。
例えば、フォーム入力項目のデータ型とAPIリクエストのデータ型が異なる場合などは、状態を分離することでその差異を保守性を担保した形で吸収できますが、この場合フォームの入力情報(表示に関する状態)がAPIリクエスト(ドメインに関する状態)に依存することで、前者の状態変化を後者に適切に反映できます。またコンポーネントから直接ドメインに関する状態を操作できないように制御できる他、TypeScriptファイルに関数同士の関係として記述されることになるのでテストが圧倒的に楽になるというメリットがあります。
実装的には、フォームの状態を管理するコンポーザブルの引数にAPIリクエストの状態を管理するコンポーザブルを受け取れるようにするということです。