先行技術
Reduxは混合した歴史を持っています。いくつかのパターンや技術と似ていますが、重要な点でそれらとは異なります。以下では、いくつかの類似点と相違点を説明します。
開発者体験
Dan Abramov(Reduxの作者)は、React Europeでの講演「“ホットリローディングとタイムトラベル”」に取り組んでいる際にReduxを作成しました。彼の目標は、最小限のAPIを持ちながら完全に予測可能な動作をする状態管理ライブラリを作成することでした。Reduxを使用すると、開発者の負担なく、ロギング、ホットリローディング、タイムトラベル、ユニバーサルアプリ、記録と再生を実装できます。
Danは、Changelogエピソード187で、彼の意図とアプローチの一部について説明しました。
影響
ReduxはFluxのアイデアを発展させたものですが、Elmの手法を取り入れることで、その複雑さを回避しています。FluxやElmを使ったことがなくても、Reduxは数分で使い始めることができます。
Flux
ReduxはFluxのいくつかの重要な特性からインスピレーションを得ています。Fluxと同様に、Reduxでは、アプリケーションの特定のレイヤー(Fluxでは「ストア」、Reduxでは「reducer」)にモデル更新ロジックを集中させることを推奨しています。アプリケーションコードが直接データを変更する代わりに、両方とも、すべての変更を「アクション」と呼ばれるプレーンオブジェクトとして記述することを指示しています。
Fluxとは異なり、**ReduxにはDispatcherの概念がありません。**これは、イベントエミッタではなく純粋関数に依存しているためであり、純粋関数は簡単に合成でき、それらを管理する追加のエンティティは必要ありません。Fluxの見方によっては、これは逸脱と見なすことも、実装の詳細と見なすこともできます。Fluxはしばしば` (state, action) => state`と説明されています。この意味で、ReduxはFluxアーキテクチャに忠実ですが、純粋関数のおかげでよりシンプルになっています。
Fluxとのもう一つの重要な違いは、**Reduxではデータを変更しないことを前提としている**ことです。状態にはプレーンオブジェクトと配列を使用できますが、reducer内でそれらを変更することは強く推奨しません。常に新しいオブジェクトを返す必要があります。これは、オブジェクトスプレッド演算子またはImmerイミュータブル更新ライブラリを使用して行うことができます。
パフォーマンス上の理由でデータを変更する不純なreducerを記述することは技術的に可能ですが、これを積極的に推奨しません。タイムトラベル、記録/再生、ホットリローディングなどの開発機能が壊れてしまいます。さらに、Omが示すように、オブジェクトの割り当てが損失しても、reducerの純粋性によって何が変更されたかが正確に分かるため、高価な再レンダリングと再計算を回避することで、ほとんどの実際のアプリケーションではイミュータビリティがパフォーマンスの問題を引き起こすとは考えられません。
ちなみに、Fluxの開発者はReduxを承認しています。Redux
Elm
Elmは、Haskellにインスパイアされた関数型プログラミング言語であり、Evan Czaplickiによって作成されました。これは「モデルビューアップデート」アーキテクチャを強制的に適用し、更新は` (action, state) => state`というシグネチャを持ちます。Elmの「updater」は、Reduxのreducerと同じ役割を果たします。
Reduxとは異なり、Elmは言語であるため、強制的な純粋性、静的型付け、すぐに使えるイミュータビリティ、パターンマッチング(`case`式を使用)などの多くの利点を享受できます。Elmを使用する予定がなくても、Elmアーキテクチャについて読んで、実際に試してみるべきです。同様のアイデアを実装した興味深いJavaScriptライブラリプレイグラウンドがあります。Reduxのインスピレーションとして参考にすべきでしょう!Elmの静的型付けにより近づける方法の1つは、Flowのような段階的な型付けソリューションを使用することです。
Immutable
Immutableは、永続的なデータ構造を実装するJavaScriptライブラリです。パフォーマンスが高く、慣習的なJavaScript APIを持っています。
(Immutable.jsはReduxのインスピレーションの1つでしたが、現在はImmerをイミュータブルな更新に使用する方が推奨されています。)
**Reduxは状態の保存方法を気にしません。プレーンオブジェクト、Immutableオブジェクト、またはその他の何でもかまいません。**ユニバーサルアプリを記述し、サーバーから状態を再水和するためには(デ)シリアライゼーションメカニズムが必要になるでしょうが、それ以外では、イミュータビリティをサポートしている限り、任意のデータストレージライブラリを使用できます。たとえば、Backboneモデルは変更可能であるため、Reduxの状態にBackboneを使用することは意味がありません。
イミュータブルライブラリがカーソルをサポートしていても、Reduxアプリではそれらを使用しないでください。状態ツリー全体は読み取り専用と見なす必要があり、Reduxを使用して状態を更新し、更新を購読する必要があります。したがって、カーソルによる書き込みはReduxでは意味がありません。**カーソルの唯一のユースケースが状態ツリーとUIツリーの結合を解除し、カーソルを徐々に洗練することだけである場合、代わりにセレクタを使用する必要があります。**セレクタは合成可能なゲッター関数です。合成可能なセレクタの非常に優れた簡潔な実装についてはreselectを参照してください。
Baobab
Baobabは、プレーンなJavaScriptオブジェクトを更新するためのイミュータブルAPIを実装するもう1つの一般的なライブラリです。Reduxと一緒に使用できますが、一緒に使用することによるメリットはほとんどありません。
Baobabが提供する機能のほとんどは、カーソルを使用してデータを更新することに関連していますが、Reduxでは、データを更新する唯一の方法はアクションをディスパッチすることです。したがって、異なる方法で同じ問題を解決しており、互いに補完し合うことはありません。
Immutableとは異なり、Baobabはまだ特別な効率的なデータ構造を内部的に実装していないため、Reduxと一緒に使用しても何も得られません。この場合は、プレーンオブジェクトを使用する方が簡単です。
RxJS
RxJSは、非同期アプリケーションの複雑さを管理するための優れた方法です。実際、ヒューマンコンピュータインタラクションを相互依存するオブザーバブルとしてモデル化するライブラリを作成する取り組みがあります。
RxJSと一緒にReduxを使用するのは理にかなっていますか?もちろんです!両者はうまく連携します。たとえば、Reduxストアをオブザーバブルとして公開するのは簡単です。
function toObservable(store) {
return {
subscribe({ next }) {
const unsubscribe = store.subscribe(() => next(store.getState()))
next(store.getState())
return { unsubscribe }
}
}
}
同様に、異なる非同期ストリームを合成してアクションに変換してから、`store.dispatch()`にフィードできます。
問題は、Rxを既に使用している場合にReduxが本当に必要かどうかです。おそらく必要ないでしょう。Rxの`.scan()`メソッドを使用すると、ReduxをRxで再実装するのは簡単です。2行でできるという人もいます。その可能性は大いにあります!
疑問がある場合は、Reduxのソースコード(それほど多くはありません)と、そのエコシステム(たとえば、開発者ツール)を確認してください。あまり気にせず、リアクティブなデータフローを最後まで進めたい場合は、Cycleのようなものを探したり、Reduxと組み合わせたりすることもできます。結果は教えてください!
お客様の声
“Reduxでの取り組みを高く評価しています” Jing Chen、Fluxの開発者
“FBの内部JSディスカッショングループでReduxについてコメントを求めたところ、満場一致で賞賛されました。本当に素晴らしい仕事です。” Bill Fisher、Fluxドキュメントの著者
“Fluxをまったく行わないことで、より良いFluxを発明しているのはクールです。” André Staltz、Cycleの開発者
謝辞
- Elmアーキテクチャ reducerを使用した状態更新のモデリングに関する素晴らしい入門資料を提供してくださったこと;
- Turning the database inside-out 私の考え方を大きく変えてくれたこと;
- Developing ClojureScript with Figwheel 再評価が「うまくいく」べきだと確信させてくれたこと;
- Webpack ホットモジュール置換機能を提供してくださったこと;
- ボイラープレートやシングルトンなしでFluxへのアプローチを学ぶためのFlummox;
- ホットリロード可能なストアの概念実証のためのdisto;
- このアーキテクチャのパフォーマンスを証明するためのNuclearJS;
- 単一の状態アトムというアイデアを普及させたOm;
- 関数が最適なツールであることを示したCycle;
- 実際的なイノベーションをもたらしたReact。
redux
NPMパッケージ名を譲渡してくれたJamie Patonに特別な感謝を。
パトロン
Reduxのオリジナルの作業はコミュニティによって資金提供されました。それを可能にした優れた企業の一部をご紹介します。
元のReduxパトロンの完全なリストと、常に増加しているReduxを使用している個人と企業のリストをご覧ください。