COLUMN
2022年11月25日
フロントエンド開発で覚えたい「状態管理」とは
カテゴリー:システム開発, テクノロジー
タグ:フロントエンド, プログラミング, フレームワーク
昨今のフロントエンド開発ではReactやVueといったフレームワークを用いて行われることが増えています。簡易的なものであれば素のJavaScriptやjQueryのようなライブラリを使うこともありますが、中規模以上であったり多人数での開発となるとフロントエンドフレームワークを利用することが多いでしょう。
そうしたフレームワークを用いる中で注意したいのが状態管理になります。状態(ステート)をどう管理するかを覚えれば、フレームワークを使いこなすのも容易になるでしょう。
本記事では、その状態管理に関する考え方や注意点について紹介します。
フロントエンド開発における状態とは
現在のWebアプリケーション開発においては、フロントエンドとバックエンドを疎結合にして開発するスタイルが一般的です。フロントエンドとバックエンドの間ではREST APIやGraphQLなどを通じてデータの送受信を行い、画面はJavaScriptによって構築します。その際、画面構築に必要な情報をバックエンドから送信します。
状態管理の考え方がないWebアプリケーションでは、HTMLの中に状態を残す形式を取ります。例えば認証したならば <div class="login">
が表示される状態になり、ログアウトしていたら非表示にすると言った具合です。そして、ログイン情報を確認する際に都度、DOMの状態を確認して処理を行います。これはとても面倒ですし、DOMはJavaScriptのどこからでも書き換えられるので、いつどこで変更されたのか知るのは困難です。
そこでReactやVueでは仮想DOMという考え方を取り入れました。バックエンドから受け取った情報を元に、動的にHTMLを生成します。そして、管理している変数が書き換わったタイミングで再描画が行われます。例えば isLogin
という変数を false
から true
に書き換えれば、ログイン状態の表示になります。逆にすれば、ログアウトした状態に書き換えられます。つまり、開発者はDOMの状態を気にする必要がなく、単にJavaScriptで変数を書き換えるだけで済むようになりました。
コンポーネント同士の連携
そしてWebアプリケーションにおいてはコンポーネント指向が取り入れられています。コンポーネント指向は、UIを部品毎に分割(コンポーネント化)し、各コンポーネントに役割を任せる仕組みです。例えばカレンダーコンポーネントだったり、認証UIのコンポーネントなどになります。こうすることで、巨大なWebアプリケーションであっても個々のコンポーネントを小さく管理し、変更時の影響範囲を小さく出来るようになっています。
コンポーネント同士は独立していますが、関連し合わない訳ではありません。例えばカレンダーであれば選択した日付を別なコンポーネントに送りたい場合もあるでしょうし、認証状態によって別なコンポーネントの表示が変わることもあるでしょう。一覧表示用のコンポーネントと、その子供(一覧表示の各行相当)コンポーネントといった具合に親子関係がある場合には親から子に対して変数を送ったり、子から親に処理を連絡することも可能です。
しかし、親子関係がない場合や、認証状態のようにWebアプリケーション全体に関係するステート(状態)についてはどうでしょうか。Webアプリケーション全体を補うAppコンポーネントがあって、そこから全てのコンポーネントに対して認証状態を伝えていくのも1つの手ですが、構造が複雑になるととても管理が面倒です。
そこで考えられたのがステート管理(状態管理)という仕組みになります。
アプリケーション全体におけるステート管理
VueやReactではWebアプリケーション全体のステート管理を用いるのが一般的です。Reactでは標準のものはありませんが、ReduxやRecoilといったステート管理が有名です。VueではVuexというステート管理が公式提供されています。こうしたステート管理は
ステート管理されている変数に対しては、変数は直接書き換えません。必要なコンポーネントに対して変更が伝達されるように、専用の仕組みを使って書き換えます。そうすることで、状態を更新すれば表示されている全コンポーネントに対して新しい状態が伝搬されます。各コンポーネント毎に状態を毎回調べ直すような手間はありません。また、変数が更新されたら画面の再描画も実行されるので、更新の通知を受け取って処理を行うと言った面倒さもありません。
ローカルステートとの棲み分け
各コンポーネント毎に管理しているステート(ローカルステート)と、Webアプリケーション全体でのステートは上手に使い分ける必要があるでしょう。昔のJavaScriptで言えば、全てをグローバルな変数にすれば管理しやすいという訳ではないでしょう。各コンポーネント内だけで使う変数であれば、ローカルステートを用いた方が分かりやすいはずです。多くの場合、ステート管理でのステート定義や更新の仕組みは、ローカルステートと比べて複雑になります。ローカルステートで済むならば、それに越したことはないでしょう。
最初はローカルステートではじめて、様々なコンポーネント間で利用する必要が出てきたらステート管理に移行しても良いでしょう。
まとめ
Webアプリケーションのフロントエンド開発は徐々に大規模化、複雑化しています。それだけフロントエンドが担う領域が大きくなっているということでしょう。それだけに旧来の方法を適用していると、すぐにメンテナンスが困難になってしまいます。
モダンな開発手法を取り入れ、中長期的にメンテナンスできる、チーム規模を拡大しても生産性の落ちない仕組みを構築してください。