Reduxに深く潜ります

Joseph Gordon-Levitt
リリース: 2025-02-14 10:13:10
オリジナル
812 人が閲覧しました

A Deep Dive into Redux

コアポイント

  • Reduxは、予測可能な状態容器として機能することにより、最新のアプリケーションの状態管理を簡素化します。これは、アプリケーションがスケーリングされたときに安定性を維持するために重要です。
  • タイプスクリプトの統合は、タイプの安全性を強制することによりReduxを強化します。これにより、予測可能性の層が追加され、リファクタリングを簡素化することで大きなコードベースを維持できます。
  • reduxの還元剤は、副作用がないことを保証するための純粋な機能として設計されており、それによって国家管理のテスト可能性と信頼性が向上します。
  • Jestを使用してユニットテストを簡素化し、JestはTypeScriptでシームレスに動作し、Reduxアクションと還元剤をテストし、すべてのコンポーネントが期待どおりに機能するようにします。
  • この記事では、給与計算エンジンを構築することにより、Reduxの実際の実装を示しており、Reduxが実際のアプリケーションシナリオで状態の遷移と副作用を扱う方法を示しています。

ステートフルな近代的なアプリケーションの構築は、複雑なタスクです。状態が変わるにつれて、アプリケーションは予測不可能で維持が困難になります。これがReduxが登場する場所です。 Reduxは、状態を処理するための軽量ライブラリです。それを州のマシンと考えてください。

この記事では、給与加工エンジンを構築することにより、Reduxの状態容器を詳細に調べます。このアプリは、ボーナスやストックオプションなどのすべてのエキストラとともに給与計算を保存します。純粋なJavaScriptとTypeScriptを使用して、ソリューションをシンプルに保つためにタイプチェックします。 Reduxは非常に簡単にテストすることができるため、Jestを使用してアプリケーションを確認します。

このチュートリアルでは、JavaScript、Node、およびNPMをある程度理解していると思います。

最初に、このアプリケーションをnpm:

で初期化できます

テストコマンドを要求するときは、Jestを使用し続けます。これは、NPM Tが冗談を開始し、すべてのユニットテストを実行することを意味します。メインファイルはindex.jsです。 NPM Initの残りの質問に気軽に答えてください。
npm init
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

タイプチェックを行い、データモデルを決定するためにTypeScriptを使用します。これは、私たちが構築しようとしているものを概念化するのに役立ちます。

TypeScriptを始めるには

開発ワークフローに依存関係のいくつかを開発します。これは、どの依存関係が開発者向けに準備され、どの依存関係が生産環境で使用されるかを明確に示しています。型タイプスクリプトの準備ができたら、package.jsonに起動スクリプトを追加:
npm i typescript --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

SRCフォルダーの下にindex.tsファイルを作成します。これにより、ソースファイルがプロジェクトの残りの部分から分離されます。 NPMを開始すると、ソリューションは実行されません。これは、TypeScriptを構成する必要があるためです。
"start": "tsc && node .bin/index.js"
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

次の構成でtsconfig.jsonファイルを作成します

この構成をTSCコマンドライン引数に配置できました。たとえば、TSC SRC/INDEX.TS - STRICT ....しかし、これらすべてを別のファイルに入れることははるかに明確です。 package.jsonの起動スクリプトには、TSCコマンドのみが必要であることに注意してください。

ここに、良い出発点とそれぞれのオプションが何を意味するかを示す合理的なコンパイラオプションがあります。

    Strict:すべての厳密なタイプのチェックオプション、つまり-noimplicitany、 - strictnullchecksなどを有効にします。
  • lib:コンパイルされたライブラリファイルのリスト。
  • Outdir:出力をこのディレクトリにリダイレクトします。
  • SourceMap:デバッグ用のソースマップファイルを生成します。
  • ファイル:コンパイラに提供される入力ファイル。
ユニットテストに冗談を言うので、それを追加し続けます:

npm init
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ts-jest依存関係テストフレームワークのタイプチェックを追加します。注意すべきことの1つは、package.jsonにJest構成を追加することです。

これにより、テストフレームワークがタイプスクリプトファイルをピックアップし、それらを変換する方法を知ることができます。素晴らしい機能は、ユニットテストを実行するときにタイプチェックを行うことができることです。このプロジェクトの準備を整えるには、index.test.tsファイルを含む__tests__フォルダーを作成します。次に、衛生チェックが行われます。たとえば、

npm i typescript --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

npm startを実行し、npm tはエラーを引き起こしません。これにより、ソリューションの構築を開始できることがわかります。しかし、これを行う前に、プロジェクトにReduxを追加しましょう:

"start": "tsc && node .bin/index.js"
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

この依存関係は、生産環境で使用されます。したがって、-save-devにそれを含める必要はありません。 Package.jsonをチェックすると、依存関係があります。

{
  "compilerOptions": {
    "strict": true,
    "lib": ["esnext", "dom"],
    "outDir": ".bin",
    "sourceMap": true
  },
  "files": [
    "src/index"
  ]
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
実際の操作でのペイストップエンジン

給与エンジンには、賃金、払い戻し、ボーナス、ストックオプションが含まれます。 Reduxでは、ステータスを直接更新することはできません。代わりに、新しい変更をストレージに通知するためにアクションがスケジュールされています。

したがって、これにより、次の操作タイプが残ります

Pay_dayの操作タイプを使用して、給料日のチェックを発行し、給与履歴を追跡できます。これらのタイプの操作は、給与エンジンを完璧にするため、残りのデザインを導きます。彼らは、基本賃金額の設定など、州のライフサイクルでイベントをキャプチャします。これらのアクションイベントは、クリックイベントであろうとデータの更新であろうと、任意のコンテンツに添付できます。 Redux操作の種類は、スケジューリングがどこから来るのかを抽象化しています。ステータスコンテナは、クライアントおよび/またはサーバーで実行できます。

typeScript

npm i jest ts-jest @types/jest @types/node --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
型理論を使用して、状態データに基づいてデータモデルを決定します。操作タイプやオプションの量など、各給与操作について。 Pay_dayは給与を処理するために資金を必要としないため、金額はオプションです。つまり、顧客に請求できますが、今のところは無視できます(おそらく第2版で紹介されます)。

たとえば、に置いてください

給与計算ステータスについては、基本給与、ボーナスなどの属性が必要です。また、このステータスを使用して給与履歴を維持します。

この型タイプスクリプトインターフェイスは、

を実行する必要があります

npm init
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

各プロパティについて、TypeScriptはコロンを使用してタイプを指定することに注意してください。たとえば、番号。これにより、タイプ契約が決定され、タイプチェッカーに予測可能性が追加されます。明示的な型宣言を備えたタイプシステムを使用して、Reduxを強化できます。これは、Redux状態容器が予測可能な動作のために構築されているためです。

このアイデアは狂ったことでも急進的でもありません。 Reduxの学習第1章(SitePoint Premiumメンバーのみ)は、これをよく説明しています。

アプリケーションが変更されると、タイプチェックは追加の予測可能性を追加します。アプリケーションが拡大するにつれて、タイプ理論は、大規模なコードセグメントの再構築を簡素化するのにも役立ちます。

タイプの概念化エンジンを使用すると、次の操作機能の作成に役立ちます。

npm i typescript --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
良いことは、ProcessBasepay( 'ABC')を実行しようとすると、タイプチェッカーが警告することです。タイプの契約を破壊すると、状態容器の予測可能性が低下します。給与計算型のような単一の操作契約を使用して、給与計算プロセッサをより予測可能にします。その量は、ES6属性の略語を介して操作オブジェクトに設定されていることに注意してください。より伝統的なアプローチは量です。量であり、これはより冗長です。 ()=>などの矢印関数は、オブジェクトリテラルを返す機能を記述する簡潔な方法です。

純粋な関数としてのレデューサー

還元剤関数には、状態と操作パラメーターが必要です。状態には、デフォルト値の初期状態が必要です。それで、あなたは私たちの最初の状態がどのように見えるか想像できますか?空の給与履歴リストからゼロから始める必要があると思います。

例:

タイプチェッカーは、これらがこのオブジェクトに属する正しい値であることを確認します。初期状態では、還元剤関数の作成を開始します:

"start": "tsc && node .bin/index.js"
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

Redux Reducerには、すべての操作タイプがスイッチステートメントで処理されるパターンがあります。しかし、すべてのスイッチケースを繰り返す前に、再利用可能なローカル変数を作成します:

{
  "compilerOptions": {
    "strict": true,
    "lib": ["esnext", "dom"],
    "outDir": ".bin",
    "sourceMap": true
  },
  "files": [
    "src/index"
  ]
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

グローバル状態を変更しない場合、ローカル変数を変更できることに注意してください。 Let Operatorを使用して、この変数が将来変更されることを伝えます。グローバルな状態(状態や運用パラメーターなど)を変更すると、レデューサーが不純になる可能性があります。この機能的なパラダイムは、還元剤機能を純粋に保つ必要があるため、重要です。初心者から忍者第11章までのJavaScript(SitePoint Premiumメンバーのみ)。

npm i jest ts-jest @types/jest @types/node --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
最初のユースケースを処理するために、減速機のスイッチステートメントを開始してください:

ES6 RESTオペレーターを使用して、州の財産を変更せずに保ちます。たとえば、...状態。残りのオペレーターの後に属性を新しいオブジェクトに上書きすることができます。ベースペイは解体から来ています。これは、他の言語でのパターンマッチングによく似ています。 ComputEToTalPay関数は次のように設定されています

"jest": {
  "preset": "ts-jest"
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
会社の株式を購入するためにお金が使用されるため、Stockoptionsを控除することに注意してください。払い戻しに対処したいとします:

npm init
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

金額はオプションであるため、障害を減らすためにデフォルト値があることを確認してください。タイプチェッカーがこのtrapを見つけて警告するので、これはタイプスクリプトの利点です。タイプシステムは特定の事実を知っているため、合理的な仮定を立てることができます。ボーナスに対処したいとします:

npm i typescript --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

このモードは、状態のみを維持するため、減速機を読みやすくします。操作の金額を取得し、合計給与を計算し、新しいオブジェクトテキストを作成します。ストックオプションを扱うときに違いはありません:

"start": "tsc && node .bin/index.js"
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

給料日に給与を処理するには、ボーナスと払い戻しを消去する必要があります。これらの2つの属性は、各給与の州に保持されていません。そして、給与履歴へのエントリを追加します。基本的な賃金とストックオプションは、頻繁に変更されないため、州に保管できます。それを念頭に置いて、これはPay_dayの処理方法です:

{
  "compilerOptions": {
    "strict": true,
    "lib": ["esnext", "dom"],
    "outDir": ".bin",
    "sourceMap": true
  },
  "files": [
    "src/index"
  ]
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

newPayHistoryのような配列では、RESTの反意語である拡張オペレーターを使用します。コレクションオブジェクトの残りのプロパティとは異なり、プロジェクトを拡張します。たとえば、[... Payhistory]。 2つの演算子は似ていますが、同じではありません。これはインタビューの質問に表示される可能性があるため、注意してください。

PAPHISTORYにPOP()を使用しても、状態は変わりません。なぜ? Slice()が新しい配列を返すためです。 JavaScriptの配列は参照によってコピーされます。新しい変数に配列を割り当てることは、基礎となるオブジェクトを変更しません。したがって、これらのタイプのオブジェクトを扱う際には注意が必要です。

lastPayHistoryは未定義の可能性が高いため、貧しい人のヌル値マージを使用してゼロに初期化します。 (o && o.property)||。 JavaScriptまたはTypeScriptの将来のバージョンでこれを行うためのよりエレガントな方法があるかもしれません。

各redux還元剤は、デフォルトのブランチを定義する必要があります。国家が未定義にならないようにするには:

npm i jest ts-jest @types/jest @types/node --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

テスト還元剤関数

純粋な機能を書くことの多くの利点の1つは、テストが簡単であることです。ユニットテストは、予測可能な動作を期待する必要があるテストであり、ビルドの一部としてすべてのテストを自動化できます。 __tests __/index.test.tsで、仮想テストをキャンセルして、関心のあるすべての機能をインポートします:

"jest": {
  "preset": "ts-jest"
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

すべての関数はエクスポートに設定されているため、インポートできます。基本給与については、給与計算エンジンの減少を開始してテストしてください。

it('is true', () => {
  expect(true).toBe(true);
});
ログイン後にコピー
ログイン後にコピー
Reduxは、初期状態を未定義に設定します。したがって、還元剤関数にデフォルト値を提供することを常にお勧めします。払い戻しを処理するのはどうですか?

npm i redux --save
ログイン後にコピー
ログイン後にコピー
ハンドリングボーナスのパターンはこれと同じです:

ストックオプションの場合:
const BASE_PAY = 'BASE_PAY';
const REIMBURSEMENT = 'REIMBURSEMENT';
const BONUS = 'BONUS';
const STOCK_OPTIONS = 'STOCK_OPTIONS';
const PAY_DAY = 'PAY_DAY';
ログイン後にコピー
ログイン後にコピー

stockoptionsがTotalPayよりも大きい場合、TotalPayは変更されないままでなければならないことに注意してください。この仮想企業は倫理的であるため、従業員からお金を受けたくありません。このテストを実行する場合は、Stockoptionsが差し引かれるため、TotalPayは-10に設定されていることに注意してください。これがコードをテストする理由です!合計給与が計算される場所を修正しましょう。
npm init
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

従業員が稼いだお金が会社の株式を購入するのに十分なお金がない場合は、引き続き控除をスキップしてください。また、Stockoptionsをゼロにリセットしていることを確認してください:

npm i typescript --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

この修正は、彼らがNewStockoptionsに十分なお金を持っているかどうかを決定します。これにより、ユニットテストが渡され、コードは健全で意味のあるものです。控除をするのに十分なお金がある肯定的なユースケースをテストすることができます:

"start": "tsc && node .bin/index.js"
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

給料日の場合、複数のステータスを使用してテストし、1回限りのトランザクションが持続しないことを確認してください。

{
  "compilerOptions": {
    "strict": true,
    "lib": ["esnext", "dom"],
    "outDir": ".bin",
    "sourceMap": true
  },
  "files": [
    "src/index"
  ]
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ボーナスを確認するために古いステートを調整し、払い戻しをゼロにリセットする方法に注意してください。

reducerのデフォルトのブランチはどうですか?

npm i jest ts-jest @types/jest @types/node --save-dev
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
Reduxは、最初にinit_actionのような操作タイプを設定します。還元剤に初期状態セットがあるかどうかのみが関心があります。

すべてのコンテンツを統合します

この時点で、Reduxがよりデザインパターンであるかどうか疑問に思うかもしれません。パターンと軽量ライブラリの両方であると答えたら、あなたは正しいです。 index.tsでは、reduxをインポート:

次のコードの例は、この声明の場合にラップできます。これはストップガップなので、ユニットテストは統合テストに漏れません:
"jest": {
  "preset": "ts-jest"
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

実際のプロジェクトでこれを行うことはお勧めしません。モジュールを別々のファイルに配置して、コンポーネントを分離できます。これにより、読みやすくなり、問題が漏れません。ユニットテストは、モジュールが独立して実行されるという事実からも恩恵を受けます。
it('is true', () => {
  expect(true).toBe(true);
});
ログイン後にコピー
ログイン後にコピー

PayrollenGinereducerを使用して、Reduxストレージを開始します:

各store.subscribe()は、クリーニングに使用できる後続のunsubscribe()関数を返します。ストレージを通じてスケジュールされたときにコールバックを登録しません。ここでは、store.getState()を使用して、現在の状態をコンソールに出力します。
npm i redux --save
ログイン後にコピー
ログイン後にコピー

従業員が300を獲得し、50の払い戻し、100のボーナス、15が会社の株式を獲得したとします。

もっと楽しくするには、別の50の払い戻しを行い、別の給与を処理します:

const BASE_PAY = 'BASE_PAY';
const REIMBURSEMENT = 'REIMBURSEMENT';
const BONUS = 'BONUS';
const STOCK_OPTIONS = 'STOCK_OPTIONS';
const PAY_DAY = 'PAY_DAY';
ログイン後にコピー
ログイン後にコピー

最後に、別の給与を実行して、reduxストレージの登録を解除してください:

interface PayrollAction {
  type: string;
  amount?: number;
}
ログイン後にコピー

最終結果は次のとおりです

interface PayStubState {
  basePay: number;
  reimbursement: number;
  bonus: number;
  stockOptions: number;
  totalPay: number;
  payHistory: Array<PayHistoryState>;
}

interface PayHistoryState {
  totalPay: number;
  totalCompensation: number;
}
ログイン後にコピー
示されているように、Reduxは状態を維持し、状態を変更し、きちんとした小さなパッケージで加入者に通知します。 Reduxを州のマシンと考えてください。これは、状態データの真のソースであるものです。これらはすべて、健全な機能パラダイムなどのコーディングベストプラクティスを採用しています。

結論
export const processBasePay = (amount: number): PayrollAction =>
  ({type: BASE_PAY, amount});
export const processReimbursement = (amount: number): PayrollAction =>
  ({type: REIMBURSEMENT, amount});
export const processBonus = (amount: number): PayrollAction =>
  ({type: BONUS, amount});
export const processStockOptions = (amount: number): PayrollAction =>
  ({type: STOCK_OPTIONS, amount});
export const processPayDay = (): PayrollAction =>
  ({type: PAY_DAY});
ログイン後にコピー

Reduxは、複雑な状態管理の問題に対する簡単なソリューションを提供します。機能的なパラダイムに依存して、予測不可能性を低下させます。還元剤は純粋な機能であるため、単体テストは非常に簡単です。 Jestを使用することにしましたが、基本的なアサーションをサポートするテストフレームワークは機能します。

TypeScriptは、タイプ理論を使用して、追加の保護層を追加します。タイプチェックを機能的なプログラミングと組み合わせると、ほとんど中断されることのない頑丈なコードが表示されます。最も重要なことは、TypeScriptが価値を追加している間、作業の邪魔にならないことです。気付いた場合、タイプ契約が整ったら、追加のエンコードはほとんどありません。タイプチェッカーは残りを行います。他の優れたツールと同様に、TypeScriptは目に見えないまま、エンコードの規律を自動化します。タイプスクリプトは大声でbarえますが、軽く噛みつきます。

このプロジェクトを試してみたい場合(これを願っています)、GitHubでこの記事のソースコードを見つけることができます。

以上がReduxに深く潜りますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート