私は読みました この答え 、 削減の定型句 、いくつかのGitHubの例を見て、さらにreduceを少し試してみました(todoアプリ)。
私が理解しているように、 公式の正規表現の動機 /伝統的なMVCアーキテクチャと比較して長所を提供します。しかしそれは質問への答えを提供していません:
なぜあなたはFacebook FluxよりもReduxを使うべきなのか?
それは、プログラミングスタイルの問題だけですか?それとも、機能的か非機能的か?あるいは、問題はreduxアプローチから得られる能力/ dev-toolsにありますか?おそらくスケーリングか、それともテスト?
reduxが関数型言語から来た人々のためのフラックスであると言ってもよろしいですか?
この質問に答えるために、フラックスとreduxに対する実装reduxの動機付けポイントの複雑さを比較することができます。
これが 公式の正規表現ドキュメントの動機からの動機のポイントです :
Reduxの著者はこちら!
ReduxはFluxとは違いませんthat。全体的には同じアーキテクチャを備えていますが、Reduxは、Fluxがコールバック登録を使用する機能構成を使用することにより、複雑さをある程度軽減できます。
Reduxには根本的な違いはありませんが、Fluxでの実装が困難または不可能である特定の抽象化を容易にするか、少なくとも実装することができます。
たとえば、ページネーションを取ります。 My Flux + React Router example はページネーションを処理しますが、そのコードはひどいです。ひどい理由の1つは、Fluxによりストア間で機能を再利用するのが不自然になることです。2つのストアが異なるアクションに応じてページネーションを処理する必要がある場合、どちらかを継承する必要があります共通のベースストアから(悪い!継承を使用すると特定のデザインにロックされます)、またはイベントハンドラー内から外部定義された関数を呼び出します。これは、何らかの方法でFluxストアのプライベート状態を操作する必要があります。全体が面倒です(ただし、可能な範囲で間違いありません)。
一方、Reduxでは、レデューサーの構成によりページネーションが自然になります。それはずっとレデューサーなので、 ページネーションレデューサーを生成するレデューサーファクトリー を記述してから レデューサーツリーで使用 を記述できます。 Fluxでを使用するとストアがフラットになりますが、ReduxではReactコンポーネントをネストできるように、機能構成を介してレデューサーをネストできるためです。 .
このパターンは、no-user-code ndo/redo のような素晴らしい機能も有効にします。2行のコードであるUndo/RedoをFluxアプリにプラグインすると想像できますか?ほとんどない。 Reduxでは、リデューサーの構成パターンのおかげで、になります。これについて新しいことは何もないことを強調する必要があります。これは、Fluxの影響を受けた Elm Architecture で先駆けて詳細に説明されているパターンです。
人々はFluxを使用してサーバーで問題なくレンダリングしていましたが、サーバーレンダリングを「より簡単に」しようとする20個のFluxライブラリがあることを確認すると、おそらくFluxにはサーバー上のラフエッジがあります。真実は、Facebookはサーバーレンダリングをあまり行わないため、Facebookはそれをあまり気にしておらず、エコシステムに依存してそれを簡単にしています。
従来のFluxでは、店舗はシングルトンです。これは、サーバー上の異なるリクエストのデータを分離するのが難しいことを意味します。不可能ではないが、難しい。これが、ほとんどのFluxライブラリ(および新しい Flux Utils )がシングルトンの代わりにクラスを使用することを示唆しているため、リクエストごとにストアをインスタンス化できる理由です。
Fluxで解決する必要がある次の問題がまだあります(自分で、または Flummox や Alt などのお気に入りのFluxライブラリの助けを借りて):
確かに、Fluxフレームワーク(Vanilla Fluxではない)にはこれらの問題に対する解決策がありますが、私はそれらが複雑すぎると感じています。たとえば、 Flummoxは、ストアにserialize()
およびdeserialize()
を実装するように要求します 。 Altは、JSONツリーの状態を自動的にシリアル化する takeSnapshot()
を提供することにより、この優れた方法を解決します。
Reduxはさらに先へ進みます:単一のストア(多くのレデューサーによって管理される)があるため、(再)水分補給を管理するための特別なAPIは必要ありません。ストアを「フラッシュ」または「ハイドレート」する必要はありません。ストアは1つだけで、現在の状態を読み取ったり、新しい状態で新しいストアを作成したりできます。各リクエストは個別のストアインスタンスを取得します。 Reduxを使用したサーバーレンダリングの詳細を参照してください。
繰り返しになりますが、これはFluxとReduxの両方で可能性のあるケースですが、Fluxライブラリは大量のAPIと規則を導入することでこの問題を解決します。Reduxは、コンセプトのシンプルさのおかげで最初の場所。
Reduxが人気のあるFluxライブラリになることは実際には意図していませんでした。作業中に書いたものです ReactEuropeのタイムトラベルを使用したホットリロードについて 。 1つの主な目的がありました:リデューサーコードをその場で変更したり、アクションを取り消して「過去を変更」したり、再計算される状態を確認したりできます。
これを行うことができる単一のFluxライブラリを見たことはありません。 React Hot Loaderもこれを実行できません。実際、Fluxストアを編集すると、Fluxストアで何をすべきか分からないため、Fluxストアを編集すると壊れます。
Reduxがリデューサーコードをリロードする必要がある場合、 replaceReducer()
を呼び出し、アプリは新しいコードで実行されます。 Fluxでは、データと関数はFluxストアで絡み合っているため、「関数を単に置き換える」ことはできません。さらに、何らかの形で新しいバージョンをDispatcherに再登録する必要があります。Reduxにはないものです。
Reduxには 豊かで成長の速いエコシステム があります。これは、 ミドルウェア などのいくつかの拡張ポイントを提供するためです。 logging 、 Promises 、 Observables 、 routing 、 不変性devチェック 、 持続性 などこれらのすべてが有用であるとは限りませんが、簡単に組み合わせて連携できるツールのセットにアクセスできると便利です。
Reduxは、Fluxのすべての利点(アクションの記録と再生、一方向のデータフロー、依存する突然変異)を保持し、Dispatcherとストア登録を導入せずに新しい利点(簡単なやり直し、ホットリロード)を追加します。
高レベルの抽象化を実装している間、正気を保つため、シンプルにすることが重要です。
ほとんどのFluxライブラリとは異なり、Redux APIの表面はごくわずかです。開発者の警告、コメント、および健全性チェックを削除すると、 99行 になります。デバッグするためのトリッキーな非同期コードはありません。
実際にそれを読んで、Reduxのすべてを理解できます。
Fluxと比較したReduxの使用の欠点に関する私の答え も参照してください。
まず、FluxなしでReactを使用してアプリを作成することは完全に可能です。
また、この視覚的な図を作成して、両方のクイックビューを表示しました。おそらく、読みたくない人のためのクイックアンサー全体の説明:
しかし、まだもっと知りたいと思うなら、読んでください。
純粋なReactから始めて、ReduxとFluxを学ぶべきだと思います。 Reactで実際の経験を積んだ後、Reduxが役立つかどうかがわかります。
Reduxがアプリにぴったりであると感じるかもしれませんし、Reduxがあなたが実際に経験していない問題を解決しようとしているのかもしれません。
Reduxから直接開始すると、コードが過剰に設計され、保守が難しくなり、Reduxを使用しない場合よりも多くのバグが発生する可能性があります。
Redux docs から:
動機
JavaScriptの単一ページアプリケーションの要件がますます複雑になるにつれて、コードはこれまで以上に多くの状態を管理する必要があります。この状態には、サーバーの応答とキャッシュされたデータ、およびサーバーにまだ永続化されていないローカルに作成されたデータが含まれます。アクティブなルート、選択したタブ、スピナー、ページネーションコントロールなどを管理する必要があるため、UIの状態も複雑になっています。この絶えず変化する状態を管理することは困難です。モデルが別のモデルを更新できる場合、ビューはモデルを更新でき、別のモデルを更新します。これにより、別のビューが更新される可能性があります。ある時点で、いつ、なぜ、どのように状態を制御できなくなったため、アプリで何が起こるか理解できなくなります。システムが不透明で非決定的である場合、バグを再現したり、新しい機能を追加したりすることは困難です。
これで十分ではないかのように、フロントエンド製品開発で一般的になっている新しい要件を検討してください。開発者として、楽観的な更新、サーバー側のレンダリング、ルートの移行を実行する前のデータのフェッチなどを処理することが期待されています。私たちは、これまで対処したことがなかった複雑さを管理しようとしていることに気付き、必然的に次の質問をします。あきらめる時ですか?答えはノーだ。
人間の心が推論するのが非常に難しい2つの概念、突然変異と非同期性を混合しているため、この複雑さを扱うのは困難です。私はそれらをメントスとコーラと呼びます。分離すると両方とも素晴らしい場合がありますが、一緒にすると混乱が生じます。 Reactなどのライブラリは、非同期と直接のDOM操作の両方を削除することにより、ビューレイヤーでこの問題を解決しようとします。ただし、データの状態の管理はユーザーに任されています。これがReduxの出番です。
Flux、CQRS、およびEvent Sourcingの足跡をたどり、Reduxは、更新が発生する方法とタイミングに特定の制限を課すことで、状態の変化を予測可能にすることを試みます。これらの制限は、Reduxの3つの原則に反映されています。
Redux docs からも:
コアコンセプト
Redux自体は非常に単純です。アプリの状態が単純なオブジェクトとして記述されていると想像してください。たとえば、todoアプリの状態は次のようになります。
{ todos: [{ text: 'Eat food', completed: true }, { text: 'Exercise', completed: false }], visibilityFilter: 'SHOW_COMPLETED' }
このオブジェクトは、セッターがないことを除いて「モデル」に似ています。これにより、コードのさまざまな部分が状態を勝手に変更できなくなり、再現が難しいバグが発生します。
状態の何かを変更するには、アクションをディスパッチする必要があります。アクションは、何が起こったかを説明する単純なJavaScriptオブジェクトです(魔法を導入しないことに注意してください)。次にいくつかのアクションの例を示します。
{ type: 'ADD_TODO', text: 'Go to swimming pool' } { type: 'TOGGLE_TODO', index: 1 } { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
すべての変更がアクションとして記述されるように強制すると、アプリで何が起こっているのかを明確に理解できます。何かが変更された場合、それが変更された理由がわかります。アクションは、起こったことのパンくずのようなものです。最後に、状態とアクションを結び付けるために、reducerと呼ばれる関数を作成します。繰り返しになりますが、それについて魔法のようなものはありません。これは、状態とアクションを引数として取り、アプリの次の状態を返すだけの関数です。大きなアプリ用にこのような関数を記述するのは難しいため、状態の一部を管理する小さな関数を記述します。
function visibilityFilter(state = 'SHOW_ALL', action) { if (action.type === 'SET_VISIBILITY_FILTER') { return action.filter; } else { return state; } } function todos(state = [], action) { switch (action.type) { case 'ADD_TODO': return state.concat([{ text: action.text, completed: false }]); case 'TOGGLE_TODO': return state.map((todo, index) => action.index === index ? { text: todo.text, completed: !todo.completed } : todo ) default: return state; } }
また、対応する状態キーに対してこれら2つのレデューサーを呼び出すことで、アプリの完全な状態を管理する別のレデューサーを作成します。
function todoApp(state = {}, action) { return { todos: todos(state.todos, action), visibilityFilter: visibilityFilter(state.visibilityFilter, action) }; }
これは基本的にReduxの全体的な考え方です。 Redux APIは使用していないことに注意してください。このパターンを容易にするいくつかのユーティリティが付属していますが、主なアイデアは、アクションオブジェクトに応じて状態が時間とともにどのように更新されるかを記述することであり、記述するコードの90%はReduxを使用しない単純なJavaScriptですそれ自体、そのAPI、または魔法。
Dan Abramovによるこの記事を読むことから始めるのが一番かもしれません。そこで彼は彼がreduxを書いていたときのFluxのさまざまな実装とそれらのトレードオフについて議論します: Flux Frameworksの進化
第二に、あなたがリンクしているその動機ページは、実際にはReduxの動機をFlux(そしてReact)の背後にある動機ほど議論していません。 Three Principles はRedux特有のものですが、それでも標準のFluxアーキテクチャとの実装上の違いは扱いません。
基本的に、Fluxは、コンポーネントとのUI/APIのやりとりに応じて状態変化を計算し、コンポーネントがサブスクライブできるイベントとしてこれらの変化をブロードキャストする複数のストアを持っています。 Reduxでは、すべてのコンポーネントがサブスクライブするストアは1つだけです。 IMOは、少なくともReduxがコンポーネントへのデータの流れを統一する(またはReduxが言うように減らす)ことによってデータの流れをさらに単純化し、統一するように感じます。モデル。
私は初期の採用者で、Facebook Fluxライブラリを使用して中規模の単一ページアプリケーションを実装しました。
会話が少し遅れているので、Facebookが彼らのFluxの実装が概念の証明であると考えるように思われ、そしてそれがそれに値する注目を受けたことがなかったことを私は最も指摘します。
非常に教育的なFluxアーキテクチャーの内部作業をより多く公開しているので、ぜひそれを使ってみることをお勧めします。これは小規模プロジェクトにとっては重要ですが、大規模プロジェクトにとっては非常に有益になります。
私たちは前進することで私たちはReduxに移行することにしました、そして私はあなたが同じことをすることを勧めます;)
これがRedux over Fluxの簡単な説明です。 Reduxにはディスパッチャはありません。リデューサーと呼ばれる純粋な機能に依存しています。ディスパッチャは必要ありません。各アクションは、1つのストアを更新するために1つ以上のリデューサーによって処理されます。データは不変なので、reducersはストアを更新する新しい更新状態を返します
より多くの情報のために フラックス対Redux
私はFluxでかなり長い時間働いていましたが、今ではReduxを使ってかなり長い時間働いています。 Danが指摘したように、両方のアーキテクチャはそれほど違いはありません。重要なのは、Reduxが物事をよりシンプルかつクリーンにするということです。それはあなたにFluxの上にいくつかのことを教えます。たとえばFluxは、一方向のデータフローの完璧な例です。データ、その操作およびビューレイヤが分離されている場合の懸念の分離。 Reduxでも同じことができますが、不変性と純粋な関数についても学びます。
2018年半ばに(数年の)ExtJSから移行した新しい反応/再採用アダプターから:
Redux学習曲線を後方にスライドさせた後、同じ質問があり、純粋な流動はOPのように単純になると考えました。
上記の回答に記載されているように、すぐにフラックスに対するリデュースの利点がわかり、それを最初のアプリに組み込みました。
ボイラープレートを再び握りながら、いくつかのother状態管理ライブラリを試しました。見つけたベストは rematch でした。
それはmuchより直感的で、バニラのreduxよりも、ボイラープレートの90%を削減し、redux(何か)に費やした時間の75%を削減しました図書館がやるべきだと思います)、私はいくつかのエンタープライズアプリをすぐに動かすことができました。
また、同じreduxツールで実行されます。これは 良い記事 であり、いくつかの利点をカバーしています。
したがって、このSOポストに「シンプルなredux」を検索して到着した他の人には、すべての利点と定型の1/4を備えたreduxの単純な代替手段として試してみることをお勧めします。
パフォーマンスを向上させるには、Reduxではなく、MobXを使用してアプリ内のデータを管理することをお勧めします。