Zustand、Jotai、Valtioの作者はなぜReact状態管理OSSを3つ開発したのか【フォーカス】

2025年6月26日

React状態管理ライブラリ開発者

加藤 大志(Daishi Kato)

OSS開発者。React状態管理ライブラリ「Zustand」(v3以降)「Jotai」「Valtio」の作者。大手電機メーカーでのリサーチャーを経て、フリーランスエンジニアとして国内外の複数の企業でソフトウェア開発に携わる。OSS活動では主にJavaScriptやReactに関連したライブラリ開発に携わり、現在は特にReactフレームワーク「Waku」に注力。
GitHub
X:@dai_shi
Zustand
Jotai
Valtio

React開発においてSPA(Single Page Application)を効率的に構築するために、アプリケーション全体の状態をどう管理するか――。すなわち「状態管理」という難解なテーマは、Web開発者たちを常に悩ませてきました

コンポーネント間でデータを共有し、パフォーマンスを維持しながら、複雑なユーザーインターフェースを構築するには、適切な状態管理の仕組みが不可欠です。この問いに対する答えはひとつではありません。そのため、Meta社が提唱した設計思想「Flux」(※1)や、Fluxに基づいた状態管理ライブラリ「Redux」(※2)が一時代を築いた後も、アプリケーションの要求や開発者の思想に合わせて、無数の状態管理ライブラリが生まれ続けています。

そんな中、「Zustand(※3)Jotai(※4)Valtio(※5)といういずれも世界中の開発者から大きな支持を集めている3つの状態管理ライブラリを手がけてきたのは、OSS開発者の加藤大志(Daishi Kato)さんです。

「Store」(※6)ベースのZustandに、「Atom」(※7)ベースのJotai、そして「Proxy」(※8)ベースのValtio――。なぜ彼は、明確に思想の異なるライブラリを3つも開発したのでしょうか。

最初から、この『三部作』をつくろうと思っていたわけではありません」とインタビューに対し語る加藤さん。その根底には、OSS開発者としてのある純粋な動機が存在していました。

(※1)Flux:Meta社(旧Facebook)が提唱した、アプリケーションのデータフローを管理するための設計思想。データが一方向に流れる「単一方向データフロー」を特徴とし、多くの状態管理ライブラリに影響を与えた。
(※2)Redux:アプリケーションの状態を一つの「Store」で集中的に管理する、予測可能な状態管理ライブラリ。2015年にリリースされた。Fluxアーキテクチャに強く影響を受けている。
(※3)Zustand:シンプルで軽量なAPIが特徴のStoreベースの状態管理ライブラリ。
(※4)Jotai:小さな状態の単位である「Atom」を組み合わせて状態を管理する、ボトムアップなアプローチが特徴のライブラリ。
(※5)Valtio:JavaScriptのProxy機能を活用し、オブジェクトを直接書き換えるような直感的な記述で状態を管理できるライブラリ。
(※6)Store:アプリケーション全体の状態を保持する単一の大きなオブジェクト。
(※7)Atom:Meta社が開発した「Recoil」というライブラリや、Jotaiで採用されている、状態の最小単位。コンポーネントは必要なAtomだけを購読することで、不要な再レンダリングを防ぐ。
(※8)Proxy:オブジェクトに対する操作(読み取り、書き込みなど)を捕捉し、独自の処理を挟み込むことができるJavaScriptの機能。

すべては「高パフォーマンスとシンプルさ」のため

――単刀直入にお聞きしますが、なぜ加藤さんは「Zustand」「Jotai」「Valtio」という、大きな人気を誇る状態管理ライブラリを3つも開発されたのでしょうか。

加藤:最初から「この3つをつくろう」との計画を立てていたわけではありませんよ。あくまで、結果的にそうなっただけです。

加藤:まず、私がReactの状態管理ライブラリにおいて実現したいゴール自体は一貫しています。「Reactアプリケーション全体で高いパフォーマンスを維持しながら、ビジネスロジックをシンプルに記述できるようにすること」です。特に私としては、どのようにして高いパフォーマンスを実現できるかに技術的な興味が強くあります。

一方で、「どうやってビジネスロジックを書くか」においては、人や組織によって求める開発スタイルが全く違います。Store型がいいという人もいれば、Atom型の方が合うという人もいるでしょう。

そして、趣味も兼ねてOSSに取り組んでいる以上、私の根底には「できれば多くの人に自分のつくったものを使ってほしい」というモチベーションがあります

そこで、「このアプローチなら、ユーザーに使ってもらえるかな」「こっちはどうだろう」との具合に、異なるアプローチで状態管理ライブラリを開発し提示していたら、気がつくと三部作になっていた……というのが正直なところです。

――試行錯誤を重ねていたら結果的に「三部作」に至っただけであって、最初からこの3ライブラリをつくろうとお考えではなかったのですね。それでは、最初に着手したのはどれでしたか?

加藤:実は「Zustand」「Jotai」「Valtio」のどれでもありません。これらに着手する前も、私は自分なりに状態管理の課題を解決できる手段を模索しており、他にも複数のライブラリを開発、公開していたんですよ。

特に力を入れていたのは、「Selector(※9)に依存しない解決方法」を探ることでした。

当時、状態管理ライブラリとして主流だったReduxでは、Selectorという仕組みが広く使われていました。

これは、「巨大な状態の中から必要な部分だけを取り出す」というものです。そして、その副次的な効果として不要な再レンダリングを防ぐこともできるため、パフォーマンス改善を目的としてSelectorが利用されることも少なくありませんでした。しかし、そのような副次的効果を主目的に据えるような手法に対し、私は少し違和感を覚えていました。

そして「そもそも、コンポーネントが実際に使った部分だけを自動で追跡してくれれば、そんな手間が不要になるのに」と感じていました。

そこで2018年ごろに私が最も注力していたのが、「React Tracked」というライブラリでした。これは、JavaScriptのProxyという機能を使い、状態オブジェクトへのアクセスを裏側で追跡し、使用された部分が変更された時だけ再レンダリングを行うことにより、レンダリングの最適化を自動で行える、というコンセプトでした。Selectorを書く必要がないというシンプルな開発体験を通して、開発者はパフォーマンスを気にせずに、アプリケーションの機能そのものに集中できる、と。

(※9)Selector:Reduxなどで使われる、Storeの巨大な状態の中からコンポーネントが必要とするデータだけを抽出するための関数。

――Proxyを使った自動最適化、ですか。反響はどうでしたか?

加藤:一定の支持は集めたものの、いくつかの壁に直面しました。

ひとつは「Internet Explorer」のような、Proxyをサポートしないブラウザがまだ存在したという、純粋な時代背景の問題です。これでは、実用的なライブラリとして提供するのが困難だった。

もうひとつは、その自動最適化の仕組みが一部の開発者から「魔法のようで、中で何が起きているか分かりにくい」と捉えられてしまったことです。「デバッグが困難になる」「内部の動作が予測できない」「何かトラブルが起きた時に対処できない」という開発者も、一定数いた。そのため、React Trackedは、爆発的な普及には至りませんでした。そして私が手がけていた他のライブラリも同様に、多くのユーザーから注目を集めるような状況にはなっていなかった。

そんなある日、「Zustandのメンテナンスを引き継いでくれないか」という話が舞い込んできました。

Zustandとの出会い。再発見した「シンプルさ」の価値

――「メンテナンスを引き継ぐ」ということは、Zustandは加藤さん自身がつくったものではないということでしょうか。

加藤:はい。

Zustandはもともと「Poimandres」という、海外のオープンソース開発者グループのメンバーが2019年に開発しました。しかし開発者当人は他のプロジェクトにリソースを集中させたいと考えており、2019年の終わりごろからメンテナンスが放置状態にあった。そのためPoimandresは引き継ぎ手を探していました。その流れで、私に声がかかったんです。

Zustandの特徴を改めて整理すると、「React Hooks(※10)でシンプルにGlobal State(※11)にアクセスできるStoreベースの状態管理ライブラリで、ContextAPI(※12)を使わずに済む軽量な設計」です。使い方が直感的で、複雑な設定やボイラープレートコードがほとんど必要ない、という点も大きな特徴です。

実は当時、私自身も試行錯誤の過程の中で、このZustandに似た「react-hooks-global-state」という状態管理ライブラリをつくっていました。React HooksでグローバルステートにアクセスするAPIを備え「ContextAPIを使わない軽量設計」といった点でZustandに似た存在です。

ですが当時はすでにZustandの方が比較的知名度が大きく、私は正直「同じようなものが存在していても意味が薄いな……」と感じていました。

そこに、「Zustandからメンテナンスを引き継がないか」との提案があったわけです。そこで「似たようなものが2つ併存し続けるよりは、Zustandに活動を集約し、より多くのユーザーに使ってもらう道に注力した方が合理的だろう」と考えたんですね。こうして私は2020年にPoimandresに加入し、同年8月公開の「バージョン3」からZustandのメンテナンスを引き継ぎました。

(※10)React Hooks:フックとも。useStateやuseEffectなど、関数コンポーネントで状態やライフサイクルといったReactの機能を利用するための仕組み。
(※11)Global State:アプリケーション内のどのコンポーネントからでもアクセスできる、全体で共有される状態。
(※12)Context API:Reactに標準で備わっている、コンポーネントツリーの深くまでpropsをバケツリレーせずにデータを渡すための仕組み。

――実際に引き継がれて、Zustandというライブラリにどのような印象をお持ちでしたか?

加藤:正直にいうと、最初は「確かにシンプルだけれど、シンプルすぎるのではないか」と感じていました。なにせ、コードベースの中心となるファイルのコアロジックは、実質的には数十行程度しかないといえるほどミニマルだったんです。

必要最小限のAPIで状態管理ができ、開発者が独自のパターンや設計を自由に組み込めるような柔軟性はあるものの、これではライブラリとして誰でも容易に真似してつくれてしまうし「果たして独自の価値を提供できているのだろうか?」と感じるところがありました。

また私自身は、React TrackedのようにProxyを使った自動最適化など、技術的に複雑なアプローチで課題を解決することに面白さを見出していたので、Zustandのシンプルさは当初、少し物足りなく感じた部分もあります。

――技術的な面白さを求める加藤さんからすると、最初は拍子抜けしてしまった部分もあったのですね。

加藤:はい。ところが、アップデートを続けていくうちにわかったのは、Zustandが「誰でも真似してつくれるくらいシンプル」であることは欠点ではなく、むしろ計り知れない価値を持っている、ということです。

だって開発者からすれば、ソースコードを読めば何をやっているかすぐに理解できるわけです。これはOSSを用いる上で常に付きまとう「このライブラリがメンテナンスされなくなったらどうしよう」という根本的なリスクを、ユーザー自身が引き下げられることを意味します。「最悪メインラインに何かあっても、自分たちでフォークしてメンテナンスを継続できる」という安心感につながる。

だからこそ、Zustandはその後私が手がけていくJotaiやValtioと比べても一番人気の位置にあり続けているのでしょうね。これは、意外な学びでした

Jotaiの誕生。創造性と情熱に火がついて

――Zustandのメンテナンスと並行するような形で、その後また新たなライブラリをつくった動機は何だったのでしょうか。

加藤:Zustandを引き継いだ前後から、私の中には次々に状態管理に関する新しいアイデアが芽生えていました。例えば当時Reactにおいては実験的な機能だった「Suspense」(※13)や「Concurrent Mode」(※14)を活用して、非同期データの読み込みやパフォーマンス最適化をより自然に扱える状態管理を模索してみたかった。

これらの新機能をZustand本体に取り入れるという選択肢もあったのですが、そうするとZustand最大の魅力である「小ささ」や「シンプルさ」が損なわれてしまう。だから、その探求は新しいライブラリでやるべきだと考えました。

そうした模索を続ける中、2020年5月にFacebook(現Meta)社から「Recoil」というライブラリが発表されました。これは私が抱えていた「Proxyを使わず、かつ従来のSelectorの仕組みに頼らずにパフォーマンスを最適化する」という長年の課題を、Atomという全く新しいモデルで解決していました。

Atomにより、状態を小さな単位に分割し、必要な部分だけを購読することで、「自動的に最適化された再レンダリング」を実現する。Recoilの発表を見て、私は「自分がやりたかったことのひとつはこれだ!」と本当に衝撃を受けましたね。

(※13)Suspense:非同期処理(データ取得など)の完了を待つ間、フォールバックUIを表示させるためのReactの機能。
(※14)Concurrent Mode:UIの応答性を保つために、レンダリングを中断・再開可能にするReactの機能群。

――まさに求めていたものだった、と。

加藤:なので思わず自分もAtomベースで何かつくりたくなったのですが、Recoilとそのまま同じようなものをつくっても仕方がないと感じていました。

だって、Meta社という大きな組織が本格的に開発しているライブラリと真正面から競合しても、個人開発では太刀打ちできませんし、仮に私が良いアイデアを思いついても、それは結局Meta社に取り込まれて終わってしまうでしょうから。

しかし、方向性を模索しているうち、RecoilのAPIでAtom等を定義する際に、識別子として文字列のキーが必須であるという点に違和感を覚えました。要するに、JavaScriptオブジェクトの参照そのものを識別子として使えない設計なんです。

各状態に必ず特段の名称をつける必要があるのですが、私はそういう命名の手間を省いて、もっと直感的にオブジェクトを扱いたかった。もっとJavaScriptらしい、オブジェクト参照ベースのシンプルなAPIをつくりたかったんですね。

すると、見た目は似ていても、向かっている設計思想のゴールが違うライブラリの形が見えてきた。「これならば単なる模倣ではなく、別の価値を提供できるし、Recoilと共存できるだろう」と。そうして開発に着手し、2020年9月に公開したのが、「文字列キーが不要で、JavaScriptオブジェクトの参照をそのまま識別子として使えて、より小さなAPIで動く、Atomベースの状態管理」という特徴を持つJotaiでした。

――そのような経緯だったのですね。Zustandの引継ぎと並行する形で挑んだJotaiの開発は、加藤さんご自身にとってどのような体験でしたか?

加藤:3つのライブラリの中でいうと、最も「ゼロからつくる」感覚に近いクリエイティブな開発だったように思います。

Zustandは既存のものを引き継いだもの。そして、後に手がけるValtioは実現したいことが最初から明確にあって、そのゴールを目指してつくる形でした。

一方で、Jotaiは、何もないところから「開発者にとって、どういうAPIが最も使いやすいか」を設計するところからスタートできた。私にとって、API設計の自由度が非常に高かったんです。

ですから、正直なところ三部作において最も面白みを感じたのは、Jotaiの開発ですね。ライブラリとして使用したときの実際の書き心地や、書いた時のロジックのイメージのしやすさも、個人的には自分にとって一番しっくりくるものなので、もしも今「3つのうち、あなた自身ならどれを使いますか?」と聞かれたら、迷わずJotaiと答えます。

Valtioという“魔法使い”の「リベンジ」

――では、Zustand、Jotaiという異なるアプローチのライブラリがすでにある中で、さらにValtioの開発に至った経緯を教えてください。

加藤:これはJotaiを公開した頃の、Poimandresチーム内での雑談がきっかけでした。

当時気がつけばZustandは「Reduxの簡易版」、Jotaiは「Recoilの簡易版」とユーザーからみられるようになっていました。実際のコードベースはもちろん大きく異なるのですが、React開発者からすると使い方やAPIの見た目が似ているため、そのように認識されていたんですね。ZustandはStoreベースでaction/dispatch(※15)パターンであるという点、JotaiはAtomベースで細かな状態管理という点で、確かにRedux、Recoilとそれぞれ共通点がある。

結果的に、我々のチームは「確立された技術を、シンプルな形で提供するのが得意な集団」という立ち位置になりつつありました。

Poimandresの面々もそのような認識があったためか、ある時メンバーの中から「じゃあ、MobX(※16)のモダンな簡易版ライブラリもつくれないか?」という話が自然に出てきたんです。

(※15)action/dispatch:状態の更新意図(Action)を、状態を管理する場所(Store)へ送る(Dispatch)という、Reduxで中心的に使われる設計パターン。
(※16)MobX:長い歴史を持つ、Proxyを活用したリアクティブな状態管理ライブラリの草分け的存在。Valtioとしばしば比較される。

――チームからの提案が発端だったのですね。

加藤:ところが私は最初、「う~ん」と難色を示しました。すでにZustandとJotaiと、2つもメンテナンスしているのに、3つ目までつくるというのは単純に面倒だというのもありましたし、何より「MobXという強力なライブラリに対して、今から似たようなライブラリをつくって違いが出せるのか。勝てるのか」と疑問に思ったからです。

やはりつくるからには真正面から競合するのではなく、違いを明確に説明できるものにしたかった。

そして、1日ほど悩んだ末に、「違いは出せる」と考えを改めました。

――悩んだといっても、1日程度だったのですね。

加藤:その鍵となったのが、冒頭でお話したReact Trackedです。

そもそもMobXの大きな特徴は、Proxyベースで状態変更を自動追跡することです。オブジェクトのプロパティへのアクセスなどを裏側で監視し、変更があった部分だけを再レンダリングする仕組みのことですね。

――それって、React Trackedと同じ……?

加藤:はい。そして私は、React TrackedでProxyベースの状態管理を開発していた時に「proxy-compare」という、どのプロパティが使用されたかを正確に追跡できる内部ライブラリをつくっていました。この資産を生かすことで、HooksのAPIによるレンダリング最適化の仕組みを持っていなかったMobXとは違うアプローチが取れると考えました。

つまり、一から技術開発をする必要がないので、実証済みの仕組みを土台にしつつ、MobXがカバーしきれていなかった「HooksのAPIによるレンダリング最適化」に注力できる。具体的には、「proxy-compare」と、内部で自動的に不変な「スナップショット」(その瞬間の状態を丸ごと写し取ったコピーのようなもの)を組み合わせることで、開発者は状態を直接書き換えるだけで不要な再レンダリングを最小限に抑えることができ、高いパフォーマンスを維持できるといったものです。「これは大きな差別化になる」と確信して開発に着手し、2020年11月にValtioを公開しました。

――React Tracked以来の、Proxyベース。当時は「魔法のようで、中で何が起きているか分かりにくい」とReact Trackedを敬遠する向きもあったとのお話もありましたが、Valtioの開発は、「Proxyベースの状態管理」という共通点において、ある種のリベンジでもあったのでしょうか。

加藤:リベンジ、ではありましたね。

振り返ると、React Trackedの頃は、Proxyであることをなるべく開発者に意識させないよう、いわば「隠す」方向で設計していました。例えば、開発者はuseTracked()というフックを使うだけで、内部でProxyによってラップされた状態オブジェクトを取得できる。つまり、APIの利用感としては、React標準のフックとほとんど変わらないようにしたんです。このようにして、ユーザーが内部実装を気にすることなく、ただ使うだけで自動的にパフォーマンスが最適化される、という体験を目指していました。

しかし、それはさっきお話した通り「中で何が起きているか分かりにくく、デバッグなどが困難になる」といった一部の開発者の懸念から、完全には受け入れられませんでした。

一方、React Trackedから数年が経過し2021年に差し掛かる頃には、もはやInternet ExplorerのようにProxyをサポートしないブラウザを考慮する必要がなくなり、開発者の間でもProxyという技術への理解が深まっていました。

そこでValtioではその発想を180度転換し、Proxyがもたらす直感的な書き心地を「前面に押し出す」ことにしたんです。「Proxyが好きな開発者」という明確なターゲットに向けたソリューションとして、です。

▲初期のValtioにおけるGitHubリポジトリ内の「README.md」(WaybackMachineにてスクリーンショット撮影)。Proxyを用いていることがわかりやすくアピールされている

――React Trackedでは「隠す」アプローチだったものを、Valtioではむしろ「前面に押し出す」アプローチに変えたのですね。

加藤: はい。その上で「状態更新の記述が、まるでただのJavaScriptオブジェクトを操作するように書ける」というシンプルさを目指しました。

具体的には、「state.count++」や「state.user.name = ‘新しい名前’」のように、特別な更新関数を呼び出すことなく、オブジェクトのプロパティを直接書き換えるような構文で状態を更新できます。この書き心地が、Proxyを生かしたValtioの最大の魅力でもあります。

かつて実現しようとしたこの開発体験を、時代が追いついたというタイミングにおいて、改めてユーザーに届けることができた。こうした狙いが奏功してか、React Trackedの時に比べてリリース後の反応も非常に良かったので、本当に嬉しかったですね。

OSSは「終わりなきパズル」

――それぞれアプローチの異なる三部作をなぜつくったのかここまでお聞きしましたが、そもそも「ひとつだけ」でReactの状態管理というテーマを完全に解決するのは困難だったわけですね。

加藤:はい。「なぜひとつのライブラリだけであらゆるニーズをカバーできる状態管理を実現しないんですか」と聞かれることがありますが、そもそもそんなことは不可能だと思うのです。どんなライブラリでも必ず、ユーザーによって開発スタイルの合わない部分がきっと出てくる。だから、3つあると。

ただ、繰り返しとはなりますが、常に「Reactアプリケーション全体で高いパフォーマンスを維持しながら、ビジネスロジックをシンプルに記述できるようにすること」というのは共通して目指してきました。そのシンプルさとは、学習コストの低い直感的なAPIであったり、定型文の少ない簡潔な記述であったり、ライブラリ自体の実装の小ささであったりするわけです。

なので、もしも「どれを使うべきか気になっている」という方がいたら、まずは3つとも少し触ってみて、ご自身の感覚で判断していただくのが一番良い、というのが私からの答えです。3つの中には、ご自身の開発スタイルに合うものと、そうでないものが必ず見つかるはずですから。

また、よく「大規模開発ならどれか」との質問も寄せられていますが、それについても私は明確なユースケースを定めていません。というのも、3つともあくまで基本的な機能を提供するプリミティブなツールだからです。大規模なチームで使うのであれば、どのライブラリを選んだとしても、チーム内で「この機能はこう使おう」というルールや共通認識をしっかりとつくることが成功の鍵になります。その点はどのツールでも変わりません。

――インタビューを通して、加藤さんの数々の言葉からは、ユーザーの存在をとにかく強く意識していることが伝わってきます。そもそも、なぜ多くの方に自身のライブラリを使ってほしいと考えてきたのでしょうか。改めて教えてください。

加藤:そうですね。

まず、私にとってOSS開発とは、本質的に「パズル」を解くような面白さがあります。世の中に存在する潜在的な課題というパズルを見つけて、コーディングという手段を通して解く。それが、純粋に面白いんです。だから私は、自分が直面している喫緊の課題を解決したいというよりは、「面白いから課題を解決したい」という動機が強い。

ただし、一人でパズルを見つけ続けるのは限界があります。

一方で、OSSの世界には、より多くの人が関わる課題という「大きなパズル」も存在します。この大きなパズルを解くのは単純に面白いですし、何より、この「大きなパズル」を解き、多くの人にOSSを使っていただけるようになると、「フィードバック」という形で、さらに新しいパズルがもらえるんです。

だから、「より多くの人に使ってもらえるかどうか」は、次の面白いパズルに出会うために非常に重要なのです。

――最後に、三部作とご自身の今後の展望についてお聞かせください。

加藤:三部作のコア機能がかなり安定してきた現在、今一番注力しているのは「Waku」という新しいReactフレームワークの開発です。

React自体がサーバーコンポーネントの導入などで大きく進化していく中で、状態管理ライブラリがさらに進化するためには、もはやライブラリ単体でできることには限界もあると感じています。フレームワークレベルでアプローチしなければ解決できない部分も大きい、と。これまでつくってきた三部作の各ライブラリをこのフレームワークにうまくつなげ、連携させていくというのが今の私の挑戦です。これからも、まだまだ尽きることのないであろう「パズル」を解き続けていければと思っています。

取材:田村 今人、前原 宗太朗
執筆・編集:田村 今人
監修:前原 宗太朗、瀬尾 光希
撮影:赤松 洋太

関連記事

人気記事

  • コピーしました

RSS
RSS