トップダウン型の状態管理 (#Redux #Zustand )と比較して知るボトムアップ型の状態管理 (#Recoil #Jotai )
はじめに
この記事はJotai公式ドキュメントのbottom-up approachというワードをきっかけに、Reactの状態管理におけるトップダウン
とボトムアップ
とは何なのかを整理したいという個人的な思いで書いています。
Jotai takes a bottom-up approach to React state management with an atomic model inspired by Recoil.
トップダウン型について
そもそもトップダウンという言葉はどこで登場するのか
Reactの公式ドキュメントではtop-downという言葉が以下のように登場します。
このデータフローは一般的には “トップダウン” もしくは “単一方向” データフローと呼ばれます。いかなる state も必ず特定のコンポーネントが所有し、state から生ずる全てのデータまたは UI は、ツリーでそれらの “下” にいるコンポーネントにのみ影響します。
親のコンポーネントから何かの値が子のコンポーネントへ渡されるこの形をトップダウンと呼びます。
何も新しいことはないですね。我々が普段useState()やContext APIを使う時に自然とやるこのデータフローをトップダウンと呼んでいます。
話をライブラリの比較に置き換える為に、トップダウン型の代表をReduxにお願いします。Zustandなどもトップダウン型になります。
Reduxの状態管理スタイルを整理
Flux/Reduxがデファクトとして世に広まった当時、"Single Source Of Truth"という言葉に染まっていたのが懐かしいです。
The global state of your application is stored in an object tree within a single store.
APIの設計で見ると、ReduxやZustandは状態を1箇所にまとめて各コンポーネントで扱います。無数のコンポーネントで構成されたReactアプリの外に”Single Source Of Truth”な状態を構成・保持しています。
例えば末端のコンポーネントで扱う必要のあるStateもトップに位置する1つの巨大なState、Store、に含めて扱います。
ReduxのようにViewライブラリに依存せずに状態管理を行おうとするライブラリは、Stateの一部がどこで扱われようがデータフローは単一方向になるようにしています。
とあるstateが複数箇所でsubscribeされていて、どこかでupdateされてもデータは大本のStoreから流れてきます。
この、データフローが1方向に限定される種類の状態管理をトップダウン型と呼べるかと思います。
ボトムアップ型について
対してボトムアップと言われると、対義語であることぐらいしか想像できません。
じゃあトップダウンで述べた事柄について、素直に反対の意味にしてみます。
Single Sourceの反対の意味? Multiple Sources?
安直ですが、Multiple Sourcesということでしょうか。
ボトムアップという言葉を考慮すると、単にStoreが複数になるだけということはなさそうですが、無下にはできなさそうです。わざわざ巨大なStoreに細かなStateを持たせなくても以下のようにできそうです。
RecoilとJotaiで、これら一つ一つのStateの単位をAtomと呼んでいます。Stateの集まりでAtomsです。
以下、ボトムアップ型のStateをAtomと呼称します。
データフローは単一方向ではなく双方向ということ?
次はデータフローについて考えてみます。トップダウンが単一方向であるならその反対は双方向でしょうか。
じゃあこうか?と絵に書いてみますが、緑で描いた矢印は少し理解に苦しみます。
(オレンジの矢印の主語はコンポーネントです。緑の矢印の主語はAtomです。)
ではこう考えてみます。トップダウン型のデータフローにおいて親はStoreでした。Stateを表現するView、Reactコンポーネント、はあくまで表現の場所であって主体にはしません。
そこでボトムアップ型は、コンポーネントも親の立場となれる、と仮定してみます。
コンポーネントはStoreではありませんが、こう表現できそうでしょうか。あくまでニュアンスで捉えて頂ければです。
RecoilやJotaiはMultipleで双方向
もう一度、ボトムアップ型を反対の言葉で述べてみると、「StoreはSingle Sourceではなく、データフローは単方向ではない」=「StoreはMultiple Sourcesで、データフローは双方向」、になります。
Atomはどこからでもupdateでき、subscribeできます。そしてAtomは好きな数だけ作ることが出来ます。AtomがAtomに依存し、影響を受けるようにも出来ます。(両ライブラリはDerivedという言葉でそれを表現し、実現しています)
Derived state is a powerful concept because it lets us build dynamic data that depends on other data.
Flexible: Derived atoms can combine other atoms
おわりに
Storeの形態で見ると、トップダウン型とはSingle Sourceとなり、ボトムアップ型とはMultiple Sourcesでした。
データフローでみると、トップダウン型は単方向であり、ボトムアップ型は双方向でした。Stateを操作する場所は一般的にはコンポーネントからですが、ボトムアップ型の場合はAtomがAtomを操作できることから、2 way、双方向と言えます。
個人的には言葉にすることでスッキリとしました。自分はRecoilとJotaiを知っているのでこれで満足ですが、ここまで読んでいただいた方にどうささったかは気になります。今後つよつよエンジニアさんがもっと綺麗に説明してくれることを期待して🙏
JotaiFriendsやってます
Jotaiファンになってこんな物をスタートしました。全部一人で作ってます。
Twitterアカウントも開設してます。
是非Jotaiが気になる方、React使いの方はフォローして頂けると嬉しいです。よろしくおねがいします!
React Fanに居ます
Jotai作者のDaishiさんが主催するReact Fanというコミュニティに自分も所属しています。Slackに居ます。こちらも是非!
Jotai Friends のテックブログです。 React状態管理ライブラリJotai(jotai.org)を新たな選択肢に。 エンジニアの皆さんが安心してJotaiを採用できるように支援します。 Powered by twitter.com/t6adev
Discussion
公式ドキュメントにすごい簡潔にまとめられてました
要するに、トップダウンは store を作ってそれを useSelector などで分解して使うこと、ボトムアップは atom を合成して store として扱うということらしいです。
なのでトップダウンかボトムアップかはレンダリングや subscribe 云々とは直接は関係なさそうです
コメントありがとうございます!
本件はトップダウン型の対となるボトムアップ型とは?という点に着目して考察してみた記事でしたので、このような体裁となりました。
なので、じゃあこのatomとは何でどう扱われるのか?今までのRedux等とどうメンタルモデルが違うんだろう、という所を個人的な観点で意見した形ですね。
あと、Reactコンポーネントでの状態管理という文脈なのでコンポーネントの登場は必要かなと思った次第です。
単にstoreの話だけならトップダウン/ボトムアップという性質は登場しないと思うのです。