Reduxアーキテクチャを改善するための10のヒント

マンダリンダック—マルコム・カーロー(CC-BY-2.0)

Reactを使い始めたとき、Reduxはありませんでした。 Fluxアーキテクチャのみがあり、競合する実装は約12個ありました。

現在、Reactのデータ管理には2つの明確な勝者があります。ReduxとMobXであり、後者はFlux実装でもありません。 Reduxは非常に人気があり、Reactに使用されているだけではありません。 Angular 2を含む他のフレームワークのReduxアーキテクチャの実装を見つけることができます。たとえば、ngrx:storeを参照してください。

サイドノート:MobXはクールであり、単純なUIの場合はReduxよりもおそらく選択するでしょう。とはいえ、MobXが提供しないReduxの重要な機能がいくつかあります。プロジェクトに最適なものを決定する前に、それらの機能を理解することが重要です。
サイドノート:リレーとFalcorは状態管理のための興味深いソリューションですが、ReduxやMobXとは異なり、それぞれGraphQLとFalcor Serverに裏打ちされている必要があり、すべてのリレー状態は一部のサーバー永続データに対応しています。私の知る限り、どちらもクライアント側のみの一時的な状態管理に適したストーリーを提供していません。 RelayまたはFalcorをReduxまたはMobXと組み合わせて、クライアントのみの状態とサーバー永続状態を区別することで、両方のメリットを享受できる場合があります。結論:現在、クライアントの州管理の明確な勝者はありません。手元の仕事に適したツールを使用します。

Reduxの作成者であるDan Abramovは、このトピックに関するいくつかの素晴らしいコースを作成しました。

  • Reduxの使用開始
  • 慣用的なReduxを使用したアプリケーションの構築

どちらもReduxの基本を説明する優れたステップバイステップチュートリアルですが、Reduxを最大限に活用するには、より高いレベルの理解も必要です。

以下は、より良いReduxアプリを構築するのに役立つヒントです。

1. Reduxの利点を理解する

Reduxには、覚えておく必要がある重要な目標がいくつかあります。

  1. 確定的ビューレンダリング
  2. 確定的な状態の再現

決定論は、アプリケーションのテスト容易性とバグの診断と修正に重要です。アプリケーションのビューと状態が非決定的である場合、ビューと状態が常に有効であるかどうかを知ることはできません。非決定論自体がバグであるとさえ言うかもしれません。

しかし、本質的に非決定的なものもあります。ユーザー入力とネットワークI / Oのタイミングなど。では、コードが本当に機能するかどうかをどのようにして知ることができますか?簡単:分離。

Reduxの主な目的は、ビューのレンダリングやネットワークの操作などのI / O副作用から状態管理を分離することです。副作用が分離されると、コードははるかに単純になります。ネットワークリクエストやDOMの更新にすべて絡み合っていない場合は、ビジネスロジックを理解してテストするのがはるかに簡単です。

ビューのレンダリングがネットワークI / Oおよび状態の更新から分離されている場合、確定的なビューのレンダリングを実現できます。つまり、同じ状態が与えられると、ビューは常に同じ出力をレンダリングします。ビューの一部をランダムに消去する非同期のものから競合状態などの問題の可能性を排除したり、ビューのレンダリング中に状態の一部を破壊したりします。

初心者がビューを作成することを考えると、「このビットにはユーザーモデルが必要なので、非同期リクエストを起動してそれを取得し、その約束が解決したら、ユーザーコンポーネントを名前で更新します。そこには少しやることが必要なので、それを取得し、約束が解決したら、それらをループして画面に描画します。」

このアプローチにはいくつかの大きな問題があります。

  1. いつでも完全なビューをレンダリングするために必要なすべてのデータがあるわけではありません。コンポーネントが処理を開始するまで、実際にはデータの取得を開始しません。
  2. ビューのレンダリングシーケンスで発生する順序を微妙に変更して、異なるフェッチタスクを異なるタイミングで実行できます。レンダーシーケンスを本当に理解するには、予測できないもの、つまり各非同期リクエストの期間に関する知識が必要です。ポップクイズ:上記のシナリオで、最初に表示されるのは、ユーザーコンポーネントまたはTo Doアイテムですか?回答:それはレースです!
  3. 場合によっては、イベントリスナーがビューステートを変化させ、別のレンダリングをトリガーし、シーケンスをさらに複雑にします。

ビューステートにデータを保存し、非同期イベントリスナーにそのビューステートを変更するためのアクセスを許可することに関する重要な問題は次のとおりです。

「非決定性=並列処理+共有状態」
〜Martin Odersky(Scalaデザイナー)
データフェッチ、データ操作、およびビューレンダーの混在は、タイムトラベルスパゲッティのレシピです。

私はB映画のSF映画でちょっとクールに聞こえることを知っていますが、信じて、時間旅行スパゲッティはそこにある最悪の味の種類です!

フラックスアーキテクチャが行うことは、厳密な分離とシーケンスを強制することであり、毎回これらのルールに従います。

  1. まず、既知の固定状態になります…
  2. 次に、ビューをレンダリングします。このレンダリングループの状態を再度変更することはできません。
  3. 同じ状態の場合、ビューは常に同じ方法でレンダリングされます。
  4. イベントリスナーは、ユーザー入力とネットワーク要求ハンドラーをリッスンします。それらが取得されると、アクションがストアにディスパッチされます。
  5. アクションがディスパッチされると、状態が新しい既知の状態に更新され、シーケンスが繰り返されます。ディスパッチされたアクションのみが状態に触れることができます。

それは一言で言えばFluxです:あなたのUIのための一方向のデータフローアーキテクチャ:

フラックスアーキテクチャ

Fluxアーキテクチャでは、ビューはユーザー入力をリッスンし、それらをアクションオブジェクトに変換します。アクションオブジェクトはストアにディスパッチされます。ストアはアプリケーションの状態を更新し、ビューに再度レンダリングするよう通知します。もちろん、ビューが入力とイベントの唯一のソースになることはめったにありませんが、それは問題ありません。追加のイベントリスナーは、ビューと同様にアクションオブジェクトをディスパッチします。

重要なことに、Fluxの状態の更新はトランザクションです。状態に対してupdateメソッドを呼び出すだけでなく、値を直接操作する代わりに、アクションオブジェクトがストアにディスパッチされます。アクションオブジェクトはトランザクションレコードです。銀行取引のように考えることができます-行われる変更の記録。銀行にデポジットしても、5分前の残高は消去されません。代わりに、新しい残高が取引履歴に追加されます。アクションオブジェクトは、トランザクション履歴をアプリケーションの状態に追加します。

アクションオブジェクトは次のようになります。

アクションオブジェクトが提供するのは、すべての状態トランザクションの実行ログを保持する機能です。そのログは、状態を決定論的な方法で再現するために使用できます。

同じ初期状態と同じ順序で同じトランザクションを指定すると、結果として常に同じ状態になります。

これには重要な意味があります。

  1. 簡単なテスト容易性
  2. 簡単な元に戻す/やり直し
  3. タイムトラベルデバッグ
  4. 耐久性—状態が一掃された場合でも、すべてのトランザクションの記録がある場合は、それを再現できます。

誰が空間と時間を熟知したくないのですか?トランザクション状態により、タイムトラベルの超大国が得られます。

Redux開発ツールの履歴スライダービュー

2.一部のアプリはReduxを必要としません

UIワークフローが単純な場合、これはすべてやり過ぎかもしれません。三目並べゲームを作っている場合、本当に元に戻す/やり直しが必要ですか?ゲームが1分以上続くことはめったにありません。ユーザーが台無しになった場合は、ゲームをリセットして、最初からやり直すことができます。

次の場合:

  • ユーザーワークフローはシンプルです
  • ユーザーは共同作業しません
  • サーバーサイドイベント(SSE)またはWebソケットを管理する必要はありません。
  • ビューごとに単一のデータソースからデータをフェッチします

アプリ内のイベントのシーケンスはおそらく十分に単純なので、トランザクション状態の利点は余分な労力の価値はありません。

アプリをFluxifyする必要はないかもしれません。そのようなアプリには、はるかに簡単なソリューションがあります。 MobXをご覧ください。

ただし、アプリの複雑さが増すにつれて、ビューステート管理の複雑さが増すにつれて、トランザクションステートの価値はそれとともに大きくなり、MobXはすぐに使用できるトランザクションステート管理を提供しません。

次の場合:

  • ユーザーワークフローは複雑です
  • アプリにはさまざまなユーザーワークフローがあります(通常のユーザーと管理者の両方を考慮してください)
  • ユーザーは共同作業ができます
  • WebソケットまたはSSEを使用しています
  • 複数のエンドポイントからデータをロードして、単一のビューを構築しています

トランザクション状態モデルから十分な利益を得ることができ、努力するだけの価値があります。 Reduxはあなたにぴったりかもしれません。

WebソケットとSSEはこれと何の関係がありますか?非同期I / Oのソースを追加すると、不確定な状態管理によりアプリで何が起こっているのかを理解するのが難しくなります。確定的な状態と状態トランザクションの記録は、このようなアプリを根本的に簡素化します。

私の意見では、ほとんどの大規模なSaaS製品には少なくともいくつかの複雑なUIワークフローが含まれており、トランザクション状態管理を使用する必要があります。ほとんどの小さなユーティリティアプリと単純なプロトタイプは、そうすべきではありません。ジョブに適したツールを使用します。

3.レデューサーを理解する

Redux =フラックス+関数型プログラミング

Fluxは一方向のデータフローとトランザクションオブジェクトをアクションオブジェクトで規定しますが、アクションオブジェクトの処理方法については何も言いません。そこでReduxが登場します。

Redux状態管理の主要な構成要素は、reducer機能です。レデューサー機能とは何ですか?

関数型プログラミングでは、共通のユーティリティ `reduce()`または `fold()`を使用して、1つの出力値を蓄積するために値のリストの各値にリデューサー関数を適用します。以下は、 `Array.prototype.reduce()`を使用してJavaScript配列に適用される加算リデューサーの例です。

Reduxは、配列を操作する代わりに、リデューサーをアクションオブジェクトのストリームに適用します。アクションオブジェクトは次のようになります。

上記のリデューサーをReduxスタイルのリデューサーに変えましょう。

これで、いくつかのテストアクションにそれを適用できます。

4.レデューサーは純粋な機能でなければなりません

決定論的な状態再現を達成するために、レデューサーは純粋な関数でなければなりません。例外なく。純粋な関数:

  1. 同じ入力が与えられると、常に同じ出力を返します。
  2. 副作用はありません。

JavaScriptで重要なのは、すべての非プリミティブオブジェクトが参照として関数に渡されることです。つまり、オブジェクトを渡して、そのオブジェクトのプロパティを直接変更すると、オブジェクトは関数の外側でも変更されます。それは副作用です。関数を呼び出すことの完全な意味を、渡したオブジェクトの完全な履歴も知らなければ知ることはできません。それは悪いことです。

代わりに、Reducerは新しいオブジェクトを返す必要があります。例えば、 `Object.assign({}、state、{thingToChange})`でそれを行うことができます。

配列パラメーターも参照です。 `.push()`は変更操作であるため、リデューサーの配列に新しいアイテム '.push() `だけを追加することはできません。同様に、 `.pop()`、 `.shift()`、 `.unshift()`、 `.reverse()`、 `.splice()`、およびその他のミューテーターメソッドも同様です。

配列で安全にしたい場合は、状態に対して実行する操作を安全なアクセサメソッドに制限する必要があります。 `.push()`の代わりに、 `.concat()`を使用します。

このチャットレデューサーの「ADD_CHAT」のケースを見てください。

ご覧のとおり、新しいオブジェクトは `Object.assign()`で作成され、 `.push()`の代わりに `.concat()`で配列に追加します。

個人的に、誤って自分の状態を変更することを心配したくないので、最近、Reduxで不変データAPIを使用して実験しています。私の状態が不変オブジェクトである場合、オブジェクトが誤って変更されていないことを知るためにコードを調べる必要さえありません。チームで作業し、偶発的な状態の変化からバグを発見した後、私はこの結論に達しました。

純粋な機能にはこれ以上のことがあります。実稼働アプリにReduxを使用する場合は、純粋な関数とは何か、時間に注意する必要があること(ロギング、乱数など)を十分に把握する必要があります。詳細については、「JavaScriptインタビューをマスターする:純粋な関数とは」を参照してください。

5.覚えておいてください:レジューサーは真実の唯一の源でなければなりません

アプリ内のすべての状態には、単一の真実のソースが必要です。つまり、状態は単一の場所に保存され、その状態が必要な他の場所は、単一の真実のソースを参照してアクセスできます。

さまざまな事柄についてさまざまな真実の情報源を持つことは問題ありません。たとえば、URLは、ユーザーリクエストパスとURLパラメーターの唯一の真実のソースである可能性があります。たぶん、あなたのアプリはあなたのAPI URLの唯一の真実のソースである設定サービスを持っています。それはいいです。しかしながら…

Reduxストアに状態を保存する場合、その状態へのアクセスはReduxを介して行う必要があります。この原則を順守しないと、古いデータや、FluxとReduxが解決するために考案した種類の共有状態突然変異バグが発生する可能性があります。

言い換えると、真実の原則の単一のソースがなければ、あなたは潜在的に失う:

  • 確定的なビューのレンダリング
  • 確定的な状態の再現
  • 簡単な元に戻す/やり直し
  • タイムトラベルデバッグ
  • 簡単なテスト容易性

状態をReduxするか、またはReduxしないでください。途中でやれば、Reduxのすべての利点を取り消すことができます。

6.アクションタイプに定数を使用する

アクション履歴を見るときに、アクションが採用されているリデューサーに簡単にトレースできるようにするのが好きです。すべてのアクションに「CHANGE_MESSAGE」のような短い一般的な名前がある場合、アプリで何が起こっているのかを理解するのが難しくなります。ただし、アクションタイプに「CHAT :: CHANGE_MESSAGE」のようなわかりやすい名前が付けられている場合は、明らかに何が起こっているかがより明確になります。

また、タイプミスをして未定義のアクション定数をディスパッチすると、アプリはエラーをスローして、間違いを警告します。アクションタイプ文字列を使用してタイプミスをすると、アクションはサイレントに失敗します。

リデューサーのすべてのアクションタイプをファイルの最上部の1か所にまとめることも役立ちます。

  • 名前の一貫性を保つ
  • レデューサーAPIをすばやく理解する
  • プルリクエストの変更点を見る

7.アクションクリエーターを使用して、ディスパッチ呼び出し元からアクションロジックを分離する

IDを生成できない、またはレデューサーで現在の時刻を取得できないと人々に伝えると、面白い外観になります。疑わしく画面を見つめている場合は、安心してください。あなたは一人ではありません。

では、アクションを使用する必要があるすべての場所で繰り返すことなく、そのような不純なロジックを処理するのに適した場所はどこですか?アクション作成者。

アクションクリエーターには他の利点もあります:

  • アクションタイプの定数をレデューサーファイルにカプセル化しておくと、他の場所にインポートする必要がなくなります。
  • アクションをディスパッチする前に、入力に対していくつかの計算を行います。
  • 定型文を減らす

アクションクリエーターを使用して、 `ADD_CHAT`アクションオブジェクトを生成しましょう。

上記のように、cuidを使用して各チャットメッセージのランダムIDを生成し、 `Date.now()`を使用してタイムスタンプを生成しています。これらはどちらもレデューサーで安全に実行できない不純な操作ですが、アクションクリエーターで実行しても問題ありません。

アクションクリエーターでボイラープレートを削減

アクションクリエーターを使用すると、プロジェクトに定型句が追加されると考える人もいます。それどころか、レデューサーのボイラープレートを大幅に削減するためにそれらをどのように使用するのかを理解しようとしています。

ヒント:定数、レデューサー、アクションクリエーターをすべて同じファイルに保存すると、別々の場所からインポートするときに必要な定型文を減らすことができます。

チャットユーザーがユーザー名と可用性ステータスをカスタマイズできるようにしたいとします。次のように、リデューサーにいくつかのアクションタイプハンドラーを追加できます。

大型の減速機の場合、これは定型的なものになる可能性があります。私が作成した多くの減速機は、それよりもはるかに複雑になる可能性があり、多くの冗長コードがあります。単純なプロパティ変更アクションをすべてまとめて折り畳むことができたらどうでしょうか?

結局のところ、それは簡単です。

余分なスペースと余分なコメントがあっても、このバージョンは短くなります。これは2つの場合にすぎません。節約は実際に合計することができます。

切り替えてはいけません…ケースは危険ですか?転落が見られます!

「switch」ステートメントを避けるべきだと、どこかで読んだことがあるかもしれません。これは、特に偶発的な失敗を避けるためと、ケースのリストが肥大化する可能性があるためです。偶発的なフォールスルーバグを見つけるのは難しいので、フォールスルーを意図的に使用すべきではないと聞いたことがあるかもしれません。それはすべて良いアドバイスですが、上記の危険について慎重に考えましょう。

  • レデューサーは構成可能であるため、ケースの膨張は問題ではありません。ケースのリストが大きくなりすぎた場合は、断片を切り離して別のレデューサーに移動します。
  • すべてのケースボディが戻るため、偶発的なフォールスルーは発生しません。グループ化されたフォールスルーケースは、キャッチを実行するボディ以外のボディを持つことはできません。

Reduxは `switch..case`をうまく使用しています。私はこの問題に関するアドバイスを公式に変更しています。上記の単純なルール(スイッチを小さくて集中し、独自のボディですべてのケースから戻る)に従う限り、 `switch`ステートメントは問題ありません。

このバージョンには異なるペイロードが必要であることに気づいたかもしれません。アクションクリエーターの出番です。

ご覧のとおり、これらのアクションクリエーターは、引数と状態の形状の変換を行っています。しかし、それだけではありません...

8.署名文書にES6パラメーターのデフォルトを使用する

Tern.jsをエディタープラグイン(Sublime TextやAtomなどの一般的なエディターで使用可能)で使用している場合、ES6のデフォルトの割り当てを読み取り、アクションクリエーターの必要なインターフェイスを推測します。インテリセンスとオートコンプリートを取得できます。これにより、開発者は必要なペイロードタイプを覚えたり、忘れたときにソースコードを確認したりする必要がないため、開発者の認知的負荷が軽減されます。

Tern、TypeScript、Flowなどの型推論プラグインを使用していない場合は、そうする必要があります。

注:型注釈ではなく、関数シグネチャで表示されるデフォルトの割り当てによって提供される推論に依存することを好みます。

  1. FlowやTypeScriptを使用して機能させる必要はありません。代わりに標準のJavaScriptを使用します。
  2. TypeScriptまたはFlowを使用している場合、TypeScriptとFlowの両方がデフォルトの割り当てからタイプを推測するため、アノテーションはデフォルトの割り当てでは冗長です。
  3. 構文のノイズが少ないほうが読みやすくなります。
  4. デフォルト設定を取得します。つまり、タイプエラーでCIビルドを停止していなくても(驚いたことになりますが、多くのプロジェクトはそうではありません)、誤った「未定義」パラメータが潜んでいることはありませんコード。

9.計算された状態とデカップリングにセレクターを使用する

チャットアプリの歴史の中で最も複雑なチャットアプリを構築しているとします。 50万行のコードを記述した後、製品チームが新しい機能要件を投げかけます。これにより、状態のデータ構造を強制的に変更することになります。

パニックする必要はありません。セレクタを使用して、アプリの残りの部分を状態の形状から切り離すのに十分なほど賢い人でした。箇条書き:回避。

私が書くほとんどすべてのレデューサーについて、ビューを構築するために必要なすべての変数を単にエクスポートするセレクターを作成します。シンプルなチャットレデューサーでどのようになるかを見てみましょう。

export const getViewState = state => state;

ええ、知っています。それはとても簡単なので、要点すらありません。あなたは私が今おかしいと思っているかもしれませんが、前に避けた弾丸を覚えていますか?このセッション中にチャットしたすべてのユーザーの完全なリストなど、計算された状態を追加する場合はどうなりますか? 「recentlyActiveUsers」と呼びましょう。

この情報は現在の状態で既に保存されていますが、簡単に入手できる方法ではありません。先に進み、 `getViewState()`で取得します。

計算された状態をすべてセレクターに入れると、次のことができます。

  1. 減速機とコンポーネントの複雑さを軽減
  2. ステートシェイプからアプリの残りの部分を切り離します
  3. 減速機内であっても、単一の真実の源泉の原則に従う

10. TDDの使用:最初にテストを書く

多くの研究では、テストファーストとテストアフターの方法論が比較されており、テストはまったく行われていません。結果は明確で劇的です。ほとんどの研究では、機能を実装する前にテストを作成した結果、出荷バグが40〜80%削減されました。

TDDは、出荷バグの密度を効果的に半分に削減することができ、その主張を裏付ける多くの証拠があります。

この記事の例を書いている間、私はそれらすべてを単体テストから始めました。

脆弱なテストを回避するために、期待を生み出すために使用した次の工場を作成しました。

これらは両方ともデフォルト値を提供することに注意してください。つまり、特定のテストに関心のあるデータのみを作成するために、プロパティを個別にオーバーライドできます。

使用方法は次のとおりです。

注:単純さのため、ユニットテストにテープを使用します。また、モカとジャスミンで2〜3年の経験があり、他の多くのフレームワークでさまざまな経験があります。選択したフレームワークにこれらの原則を適応させることができるはずです。

ネストされたテストを記述するために開発したスタイルに注意してください。おそらく、JasmineとMochaを使用した私のバックグラウンドのために、まず外側のブロックでテストするコンポーネントを説明し、次に内側のブロックでコンポーネントに渡すものを説明するのが好きです。内部では、テストライブラリの `deepEqual()`または `toEqual()`関数で実行できる単純な等価アサーションを作成します。

ご覧のとおり、私は `beforeEach()`や `afterEach()`のようなユーティリティの代わりに分離されたテスト状態とファクトリー関数を使用します。 。

おそらくご想像のとおり、各減速機には3種類のテストがあります。

  1. あなたが今見たばかりの直接還元剤テスト。これらは基本的に、リデューサーが予想されるデフォルト状態を生成することをテストします。
  2. アクションクリエーターテスト。所定の状態を開始点として使用して、リデューサーをアクションに適用することにより、各アクションクリエーターをテストします。
  3. セレクターテスト。セレクターをテストして、予想されるすべてのプロパティが存在することを確認します(予想される値を持つ計算されたプロパティを含む)。

あなたはすでに減力剤のテストを見てきました。他の例を見てみましょう。

Action Creatorテスト

この例は、いくつかの理由で興味深いものです。 `addChat()`アクション作成者は純粋ではありません。つまり、値のオーバーライドを渡さない限り、生成されるすべてのプロパティに特定の期待をすることはできません。これに対処するために、パイプを使用しました。これは、必要のない余分な変数の作成を避けるために時々使用します。生成された値を無視するために使用しました。それらが存在することは確認していますが、値が何であるかは気にしません。タイプをチェックすることすらないことに注意してください。それを処理するために、型推論とデフォルト値を信頼しています。

パイプは、それぞれが前の関数の出力を取得して何らかの方法で変換する一連の関数を介して入力値を往復できる機能的なユーティリティです。 「lodash / fp / pipe」からのlodashパイプを使用します。これは「lodash / flow」のエイリアスです。興味深いことに、 `pipe()`自体はリデューサー関数で作成できます:

状態遷移を単純化するために、reducerファイルでも `pipe()`を多く使用する傾向があります。最終的にすべての状態遷移は、あるデータ表現から次のデータ表現に移動するデータフローです。それが「pipe()」の得意なところです。

アクション作成者はすべてのデフォルト値をオーバーライドできるため、特定のIDとタイムスタンプを渡し、特定の値をテストできます。

セレクターテスト

最後に、状態セレクターをテストし、計算された値が正しいこと、およびすべてが正常であることを確認します。

このテストでは、 `Array.prototype.reduce()`を使用して、いくつかの例の `addChat()`アクションを削減していることに注意してください。 Reduxレデューサーの優れた点の1つは、通常のレデューサー関数であるということです。つまり、他のレデューサー関数を使用して行うことができることを意味します。

`expected`値は、すべてのチャットオブジェクトがログにあること、および最近アクティブになったユーザーが正しくリストされていることを確認します。

それについて言うことは他にあまりありません。

Reduxルール

Reduxを正しく使用すると、大きなメリットが得られます。

  • タイミング依存のバグを排除
  • 確定的なビューレンダリングを有効にする
  • 確定的な状態再現を有効にする
  • 簡単な元に戻す/やり直し機能を有効にする
  • デバッグを簡素化する
  • タイムトラベラーになる

ただし、そのいずれかが機能するためには、いくつかのルールを覚えておく必要があります。

  • レデューサーは純関数でなければなりません
  • 還元剤は、その状態の唯一の真実の源でなければなりません
  • レデューサーの状態は常にシリアル化可能でなければなりません
  • 減速機の状態には関数を含めるべきではありません

また、留意してください:

  • 一部のアプリはReduxを必要としません
  • アクションタイプに定数を使用する
  • アクションクリエーターを使用して、ディスパッチ呼び出し元からアクションロジックを分離する
  • 自己記述署名にES6パラメーターのデフォルトを使用する
  • 計算された状態とデカップリングにセレクターを使用する
  • 常にTDDを使用してください!

楽しい!

DevAnywhereでReduxスキルをレベルアップする準備はできていますか?

高度な関数型プログラミング、React、およびReduxを1:1のメンターシップで学びます。 Lifetime Accessのメンバーは、関数型プログラミングとReduxのレッスンをご覧ください。 ReactとReduxを使用して実際のアプリを構築するときは、必ずShotgunシリーズを見て、ショットガンに乗ってください。

https://devanywhere.io/

エリックエリオットは「プログラミングJavaScriptアプリケーション」(O’Reilly)の著者であり、DevAnywhere.ioの共同設立者です。彼は、Adobe Systems、Zumba Fitness、The Wall Street Journal、ESPN、BBC、およびUsher、Frank Ocean、Metallicaなどのトップレコーディングアーティストのソフトウェアエクスペリエンスに貢献しています。

彼は、世界で最も美しい女性と、どこでも好きな場所で仕事をしています。