Redux・はじめに

公開: 2022-03-10
簡単なまとめ↬Reduxは、最近のフロントエンド開発で最も人気のあるライブラリの1つです。 しかし、多くの人々はそれが何であるか、そしてその利点が何であるかについて混乱しています。 ドキュメントに記載されているように、ReduxはJavaScriptアプリの予測可能な状態コンテナーです。 言い換えると、これは従来のライブラリやUnderscore.jsやAngularJSのようなフレームワークではなく、アプリケーションのデータフローアーキテクチャです。

Reduxは、最近のフロントエンド開発で最も人気のあるライブラリの1つです。 しかし、多くの人々はそれが何であるか、そしてその利点が何であるかについて混乱しています。

ドキュメントに記載されているように、ReduxはJavaScriptアプリの予測可能な状態コンテナーです。 言い換えると、これは従来のライブラリやUnderscore.jsやAngularJSのようなフレームワークではなく、アプリケーションのデータフローアーキテクチャです。

SmashingMagの詳細

  • モバイルアプリのReactNativeを検討する理由
  • アプリ、ゲーム、モバイルWebのテスト自動化
  • React、Node、Expressを使用したサーバーサイドレンダリング
  • クライアントがレンダリングするアクセシビリティに関する注記

Reduxは、2015年6月頃にDan Abramovによって作成されました。これは、FacebookのFluxと関数型プログラミング言語のElmに触発されました。 Reduxは、そのシンプルさ、サイズの小ささ(2 KBのみ)、優れたドキュメントにより、すぐに人気を博しました。 Reduxが内部でどのように機能するかを学び、ライブラリを深く掘り下げたい場合は、Danの無料コースをチェックすることを検討してください。

ジャンプした後もっと! 以下を読み続けてください↓

Reduxは主にアプリケーションの状態管理に使用されます。 要約すると、Reduxはアプリケーション全体の状態を単一の不変の状態ツリー(オブジェクト)に保持します。これは直接変更することはできません。 何かが変更されると、新しいオブジェクトが作成されます(アクションとレデューサーを使用)。 以下では、コアコンセプトについて詳しく説明します。

MVCやFluxとどう違うのですか?

ほとんどの開発者はそれに精通しているので、いくつかの視点を与えるために、古典的なモデル-ビュー-コントローラー(MVC)パターンを取り上げましょう。 MVCアーキテクチャでは、データ(モデル)、プレゼンテーション(ビュー)、ロジック(コントローラー)が明確に分離されています。 これには、特に大規模なアプリケーションで1つの問題があります。それは、データの流れが双方向であるということです。 これは、1つの変更(ユーザー入力またはAPI応答)がコード内の多くの場所でアプリケーションの状態に影響を与える可能性があることを意味します(たとえば、双方向のデータバインディング)。 これは、保守とデバッグが難しい場合があります。

FluxはReduxと非常によく似ています。 主な違いは、Fluxにはアプリケーションの状態を変更する複数のストアがあり、これらの変更をイベントとしてブロードキャストすることです。 コンポーネントはこれらのイベントをサブスクライブして、現在の状態と同期できます。 Reduxにはディスパッチャーがありません。ディスパッチャーはFluxで、登録されたコールバックにペイロードをブロードキャストするために使用されます。 Fluxのもう1つの違いは、多くの種類が利用可能であり、混乱と矛盾が生じることです。

Reduxのメリット

「なぜReduxを使用する必要があるのですか?」と質問されるかもしれません。 素晴らしい質問です。 次のアプリケーションでReduxを使用することにはいくつかの利点があります。

  • 結果の予測可能性
    現在の状態をアクションやアプリケーションの他の部分と同期する方法について混乱することなく、信頼できる唯一の情報源であるストアが常に存在します。
  • 保守性
    予測可能な結果と厳密な構造を持つことで、コードの保守が容易になります。
  • 組織
    Reduxは、コードの編成方法をより厳密にします。これにより、コードの一貫性が高まり、チームでの作業が容易になります。
  • サーバーレンダリング
    これは、特に初期レンダリングに非常に役立ち、ユーザーエクスペリエンスや検索エンジン最適化を向上させます。 サーバー上に作成されたストアをクライアント側に渡すだけです。
  • 開発者ツール
    開発者は、アクションから状態の変化まで、アプリで行われているすべてをリアルタイムで追跡できます。
  • コミュニティとエコシステム
    これは、ライブラリやフレームワークを学習または使用しているときはいつでも大きなプラスになります。 Reduxの背後にコミュニティがあると、使用するのがさらに魅力的になります。
  • テストのしやすさ
    テスト可能なコードを作成する最初のルールは、1つのことだけを実行し、独立した小さな関数を作成することです。 Reduxのコードは、ほとんどがそれだけの関数です。小さく、純粋で、孤立しています。

関数型プログラミング

前述のように、Reduxは関数型プログラミングの概念に基づいて構築されました。 これらの概念を理解することは、Reduxがそのように機能する方法と理由を理解するために非常に重要です。 関数型プログラミングの基本的な概念を確認しましょう。

  • 関数をファーストクラスのオブジェクトとして扱うことができます。
  • 関数を引数として渡すことができます。
  • 関数、再帰、配列を使用してフローを制御できます。
  • 純粋、再帰、高階、クロージャ、無名関数を使用できます。
  • map、filter、reduceなどのヘルパー関数を使用できます。
  • 機能を連鎖させることができます。
  • 状態は変化しません(つまり、不変です)。
  • コードの実行順序は重要ではありません。

関数型プログラミングにより、よりクリーンでモジュール式のコードを記述できます。 スコープとロジックが分離された、より小さくシンプルな関数を作成することで、コードのテスト、保守、およびデバッグをはるかに簡単にすることができます。 これで、これらの小さな関数は再利用可能なコードになります。これにより、記述できるコードが少なくなり、コードを少なくすることができます。 関数は、変更なしでどこにでもコピーして貼り付けることができます。 スコープが分離され、1つのタスクのみを実行する関数は、アプリ内の他のモジュールへの依存度が低くなります。この結合の減少は、関数型プログラミングのもう1つの利点です。

01-関数型プログラミング-opt-preview
関数型プログラミングの例(画像:Tanya Bachuk)(拡大版を表示)

関数型JavaScriptを使用する場合、純粋関数、無名関数、クロージャ、高階関数、メソッドチェーンなどがよく見られます。 Reduxは純粋関数を多用するため、それらが何であるかを理解することが重要です。

純粋関数は、渡された引数に基づいて新しい値を返します。 既存のオブジェクトは変更されません。 代わりに、新しいものを返します。 これらの関数は、呼び出された状態に依存せず、提供された引数に対して1つだけ同じ結果を返します。 このため、それらは非常に予測可能です。

純粋関数は値を変更しないため、スコープや観察可能な副作用に影響を与えることはありません。つまり、開発者は純粋関数が返す値にのみ焦点を当てることができます。

Reduxはどこで使用できますか?

ほとんどの開発者はReduxをReactに関連付けていますが、他のビューライブラリでも使用できます。 たとえば、ReduxはAngularJS、Vue.js、Polymer、Ember、Backbone.js、Meteorで使用できます。 ただし、ReduxとReactは依然として最も一般的な組み合わせです。 正しい順序でReactを学ぶようにしてください。最良のガイドはPeteHunt'sです。これは、Reactを使い始めて、エコシステムで起こっていることすべてに圧倒されている開発者にとって非常に役立ちます。 JavaScriptの疲労は、初心者でも経験豊富でも、フロントエンド開発者の間で正当な懸念事項です。時間をかけて、ReactまたはReduxを正しい方法で正しい順序で学習してください。

Reduxが素晴らしい理由の1つは、そのエコシステムです。 非常に多くの記事、チュートリアル、ミドルウェア、ツール、定型文が利用可能です。 個人的には、David Zukowskiの定型文を使用しています。これは、React、Redux、ReactRouterを使用してJavaScriptアプリケーションを構築するために必要なものがすべて揃っているためです。 注意点:ReactやReduxなどの新しいフレームワークを学習するときは、ボイラープレートやスターターキットを使用しないようにしてください。 すべてがどのように連携するかを理解できないため、さらに混乱します。 最初にそれを学び、理想的にはサイドプロジェクトとして非常にシンプルなアプリを構築してから、本番アプリにボイラープレートを使用して時間を節約します。

Reduxのパーツの構築

Reduxの概念は複雑または派手に聞こえるかもしれませんが、単純です。 ライブラリはわずか2KBであることに注意してください。 Reduxには、アクション、ストア、レデューサーの3つの構成要素があります。

02-redux-data-flow-opt-preview
Reduxデータフロー(画像:Tanya Bachuk)(拡大版を表示)

それぞれが何をするかについて話し合いましょう。

行動

一言で言えば、アクションはイベントです。 アクションは、アプリケーションからデータ(ユーザーインタラクション、API呼び出しなどの内部イベント、フォーム送信)をストアに送信します。 ストアは、アクションからのみ情報を取得します。 内部アクションは、 typeプロパティ(通常は定数)を持つ単純なJavaScriptオブジェクトであり、アクションのタイプとストアに送信される情報のペイロードを記述します。

 { type: LOGIN_FORM_SUBMIT, payload: {username: 'alex', password: '123456'} }

アクションは、アクションクリエーターで作成されます。 それは明白に聞こえます、私は知っています。 これらは、アクションを返す関数にすぎません。

 function authUser(form) { return { type: LOGIN_FORM_SUBMIT, payload: form } }

したがって、アプリ内の任意の場所でアクションを呼び出すのは非常に簡単です。 次のように、 dispatch方法を使用します。

 dispatch(authUser(form));

レデューサー

関数型JavaScriptのレデューサーとは何かについてはすでに説明しました。 これは配列reduceメソッドに基づいており、コールバック(reducer)を受け入れ、複数の値、整数の合計、または値のストリームの累積から単一の値を取得できます。 Reduxでは、レデューサーはアプリケーションの現在の状態とアクションを取得してから新しい状態を返す関数(純粋)です。 レデューサーはほとんどの作業を実行するため、レデューサーがどのように機能するかを理解することが重要です。 これは、現在の状態とアクションを引数として取り、次の状態を返す非常に単純なレデューサーです。

 function handleAuth(state, action) { return _.assign({}, state, { auth: action.payload }); }

より複雑なアプリの場合、Reduxが提供するcombineReducers()ユーティリティを使用することが可能です(実際、推奨)。 アプリ内のすべてのレデューサーを1つのインデックスレデューサーに結合します。 すべてのレデューサーはアプリの状態の独自の部分を担当し、状態パラメーターはレデューサーごとに異なります。 combineReducers()ユーティリティを使用すると、ファイル構造の保守がはるかに簡単になります。

オブジェクト(状態)が一部の値のみを変更した場合、Reduxは新しいオブジェクトを作成します。変更されなかった値は古いオブジェクトを参照し、新しい値のみが作成されます。 それはパフォーマンスに最適です。 さらに効率的にするために、Immutable.jsを追加できます。

 const rootReducer = combineReducers({ handleAuth: handleAuth, editProfile: editProfile, changePassword: changePassword });

Storeは、アプリケーションの状態を保持するオブジェクトであり、状態にアクセスし、アクションをディスパッチし、リスナーを登録するためのいくつかのヘルパーメソッドを提供します。 状態全体が1つのストアで表されます。 すべてのアクションは、レデューサーを介して新しい状態を返します。 これにより、Reduxは非常にシンプルで予測可能になります。

 import { createStore } from 'redux'; let store = createStore(rootReducer); let authInfo = {username: 'alex', password: '123456'}; store.dispatch(authUser(authInfo));

開発者ツール、タイムトラベル、ホットリロード

特に大規模なアプリケーションで作業する場合に、Reduxを使いやすくするために、ReduxDevToolsを使用することをお勧めします。 これは非常に役立ち、時間の経過に伴う状態の変化、リアルタイムの変化、アクション、および現在の状態を示します。 これにより、 console.logの現在の状態とアクションを回避することで、時間と労力を節約できます。

03-redux-dev-tools-opt-preview
Redux DevTools(ラージバージョンを表示)

Reduxのタイムトラベルの実装はFluxとは少し異なります。 Reduxでは、前の状態に戻ったり、その時点から別の方向に状態を変更したりすることもできます。 Redux DevToolsは、Reduxワークフローで次の「タイムトラベル」機能をサポートしています(これらを州のGitコマンドと考えてください)。

  • リセット:ストアが作成された状態にリセットします
  • 元に戻す:最後にコミットされた状態に戻ります
  • スイープ:誤って実行した可能性のある無効なアクションをすべて削除します
  • コミット:現在の状態を初期状態にします

タイムトラベル機能は本番環境では効率的ではなく、開発とデバッグのみを目的としています。 DevToolsについても同じことが言えます。

Reduxは、機能的なJavaScriptをベースとして使用し、小さな独立した関数を簡単にテストできるため、テストがはるかに簡単になります。 したがって、状態ツリーで何かを変更する必要がある場合は、その状態を担当するレデューサーを1つだけインポートし、それを個別にテストします。

アプリを作成する

この入門ガイドを締めくくるために、ReduxとReactを使用して非常に単純なアプリケーションを作成しましょう。 誰もが簡単にフォローできるようにするために、ECMAScript 2015および2016をできるだけ使用せずに、単純な古いJavaScriptを使用します。 この投稿の前半で開始したログインロジックを続行します。 このアプリの目的は、Reduxが非常に単純なアプリの状態をどのように管理するかを示すことであるため、この例ではライブデータを使用していません。 CodePenを使用します。

1.Reactコンポーネント

いくつかのReactコンポーネントとデータが必要です。 簡単なコンポーネントを作成して、ページにレンダリングしてみましょう。 コンポーネントには、入力フィールドとボタンがあります(これは非常に単純なログインフォームです)。 以下に、状態を表すテキストを追加します。

CodePenのAlexBachuk(@abachuk)によるReduxのペンイントロを参照してください。

CodePenのAlexBachuk(@abachuk)によるReduxのペンイントロを参照してください。

2.イベントとアクション

プロジェクトにReduxを追加し、ボタンのonClickイベントを処理してみましょう。 ユーザーがログインするとすぐに、タイプLOGINと現在のユーザーの値でアクションをディスパッチします。 その前に、ストアを作成し、それにレデューサー関数を引数として渡す必要があります。 今のところ、レデューサーは空の関数になります。

Reduxのペンイントロ-ステップ2を参照してください。CodePenのAlexBachuk(@abachuk)によるイベントとアクション。

Reduxのペンイントロ-ステップ2を参照してください。CodePenのAlexBachuk(@abachuk)によるイベントとアクション。

3.レデューサー

アクションが起動したので、レデューサーはそのアクションを実行して新しい状態を返します。 ログイン状態を返すLOGINアクションを処理し、後で使用できるようにLOGOUTアクションを追加してみましょう。 authレデューサーは2つのパラメーターを受け入れます。

  1. 現在の状態(デフォルト値)、
  2. アクション。

Reduxのペンイントロ-ステップ3を参照してください。CodePenのAlexBachuk(@abachuk)によるレデューサー。

Reduxのペンイントロ-ステップ3を参照してください。CodePenのAlexBachuk(@abachuk)によるレデューサー。

4.現在の状態を表示する

これで、初期状態(レデューサーのデフォルト値)とReactコンポーネントの準備ができたので、状態がどのように見えるかを見てみましょう。 ベストプラクティスは、状態を子コンポーネントにプッシュダウンすることです。 コンポーネントが1つしかないため、アプリの状態をプロパティとしてauthコンポーネントに渡します。 すべてを連携させるには、 ReactDOM.renderを関数でラップし、それをstore.subscribe()に渡すことにより、ストアリスナーをsubscribeヘルパーメソッドに登録する必要があります。

Pen Intro to Redux-ステップ4を参照してください。CodePenでのAlexBachuk(@abachuk)による現在の状態の表示。

Pen Intro to Redux-ステップ4を参照してください。CodePenでのAlexBachuk(@abachuk)による現在の状態の表示。

5.ログインとログアウト

ログインおよびログアウトアクションハンドラーができたので、ログアウトボタンを追加してLOGOUTアクションをディスパッチしましょう。 最後のステップは、このログインをrenderメソッドの外に移動し、変数を下にレンダリングすることによって、ログインまたはログアウトを表示するボタンを管理することです。

Reduxのペンイントロ-ステップ5を参照してください。CodePenでのAlexBachuk(@abachuk)によるログイン/ログアウト。

Reduxのペンイントロ-ステップ5を参照してください。CodePenでのAlexBachuk(@abachuk)によるログイン/ログアウト。

結論

Reduxは毎日勢いを増しています。 多くの企業(Uber、Khan Academy、Twitter)や多くのプロジェクト(Apollo、WordPressのCalypso)で使用されており、本番環境で成功を収めています。 一部の開発者は、多くのオーバーヘッドがあると不平を言うかもしれません。 ほとんどの場合、ボタンのクリックや単純なUIの変更などの単純なアクションを実行するには、より多くのコードが必要です。 Reduxはすべてに完全に適合するわけではありません。 バランスが必要です。 おそらく、単純なアクションとUIの変更は、Reduxストアの一部である必要はなく、コンポーネントレベルで維持できます。

Reduxはアプリやフレームワークにとって理想的なソリューションではないかもしれませんが、特にReactアプリケーションの場合はチェックすることを強くお勧めします。

フロントページの画像クレジット:Lynn Fisher、@ lynnandtonic