前回は、Reduxの役割と基礎知識について学びました。
Reduxは、同じアプリケーション内であれば、状態(state)をどこからでもアクセスして、値を変更できるようした。
Reduxには
- Store (ストア) … アプリケーション全体の状態を保存しているオブジェクトです。
- Action (アクション) … 状態の変更を作成します。
- Dispatch (ディスパッチ) … Actionで設定した値をStoreへ送ります
- Reduce (リデュース) … 現在の状態と送られてきたActionを受け取り新しい状態を作成します。
がありました。
今回は、下記のようなことを勉強しました。
Switch ステートメントを使用して複数のアクションを処理する
Reduxで複数のアクションのタイプを処理する場合、switch構文を用いることができるようです。
Reduxのstoreで、ユーザー認証を管理しており、
- ユーザーがログインしている時
- ユーザーがログアウトしている時
この2つの状態を管理する必要があったとします。
例えば、下記のような課題で、
コードエディターに、ストア、アクション、そしてアクションクリエイターが用意されています。 複数の認証アクションを処理するように
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/use-a-switch-statement-to-handle-multiple-actionsreducer
関数を記述してください。reducer
で JavaScript のswitch
ステートメントを使用して、さまざまなアクションイベントに応答してください。 これは Redux のレデューサーを記述する際の標準的なパターンになります。 switch ステートメントでは、action.type
に応じて処理を切り替え、適切な認証状態を返してください。
解答としては、下記のようになりました。
アクションタイプに const を使用する
Reduxでは、アクションタイプの値は、読み取り専用の定数として割り当てられることが多いようです。
また、
一般的に、定数はすべて大文字で記述することが慣習になっていて、Redux でも標準的になっています
下記のような課題がありました。
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/use-const-for-action-types
LOGIN
およびLOGOUT
をconst
値として宣言し、それぞれに文字列'LOGIN'
および'LOGOUT'
を割り当ててください。 次に、authReducer()
とアクションクリエイターを編集して、文字列値ではなくそれらの定数を参照するようにしてください。
解答としては下記のようになりました。
<iframe src="https://codesandbox.io/embed/freecodecamp-akusiyontaipuni-const-woshi-yong-suru-qd9ylw?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="freeCodeCamp : アクションタイプに const を使用する"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
ストアリスナーを登録する
ストアリスナーという名前だったので、よくわからなかったのですが、
actionがディスパッチされる度に関数が実行されます。
どういう時に実行されるのか、
- デバッグ: ストアの状態変更をリアルタイムに監視して、デバッグ情報やログをコンソールに表示することができます。これにより、アプリケーションの動作をトラッキングし、問題の特定や解決が容易になります。
- ロギング: アクションがディスパッチされたときに、特定の操作やイベントのログを記録することができます。これは、アプリケーションの使用状況を追跡し、分析する際に役立ちます。
- 状態の同期: ストアの状態変更に応じて、ローカルストレージなどの外部データベースにデータを同期する場合に使えます。これにより、アプリケーションの状態を永続化することができます。
- UIの更新: ストアの状態変更に応じて、Reactコンポーネントを再レンダリングしてUIを更新することができます。これにより、アプリケーションの見た目をリアルタイムに変更できます。
どのように、定義するのかというと
store.subscribe()
注意点として、
store.subscribe()
メソッドは非同期処理を含む場合が多いため、適切に管理しないとメモリリークやパフォーマンスの問題が発生する可能性があるようです。そのため、必要なタイミングでサブスクライブを解除することが重要だそうです。
メモリリーク : メモリリーク(Memory Leak)とは、プログラムが使用しているメモリ領域のうち、不要になったにもかかわらず解放されずに残ってしまう現象のことを指します。これは、プログラムがメモリを効率的に管理できていないことによって発生します。
メモリリークなどを防ぐのに役に立つのが、
store.unsubscribe()
サブスクライブした関数は、必要に応じていつでも store.unsubscribe() を呼び出すことで解除することもできます。
下記のような課題がありました。
ストアがアクションを受信するたびにグローバル変数
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/register-a-store-listenercount
を 1 増やすコールバック関数を記述し、この関数をstore.subscribe()
メソッドに渡してください。 アクションオブジェクトを直接渡すたびに、store.dispatch()
が 3 回連続して呼び出されることがわかります。 アクションがディスパッチされる合間のコンソール出力を表示して、更新が行われる様子を確認してください。
解答はこのようになりました。
複数のレデューサーを結合する
アプリが複雑になってくると、storeの中で分割して状態を管理したくなる場合があるそうです。
しかし、Reduxでは、原則として「すべてのアプリの状態はストア内の単一の状態オブジェクトに保持される」という原則がありました。
なので、Reduxでは、手段としてレデューサーコンポジションというものがあるそうです。
色々なコンポーネントで定義されたレデューサーを1つのルートリデューサーとしてまとめることができるようです。
combineReducers()
使用方法としては、
const rootReducer = Redux.combineReducers({
auth: authenticationReducer,
notes: notesReducer
});
このメソッドはオブジェクトを引数として受け取り、オブジェクトでは、特定のレデューサー関数にキーを関連付けるプロパティを定義しているようです。 Redux は、キーに付けられた名前を、state の関連付けられた部分を示す名前として使用されているようです。
下記のような課題がありました。
コードエディターに
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/combine-multiple-reducerscounterReducer()
関数とauthReducer()
関数が Redux ストアとともに用意されています。Redux.combineReducers()
メソッドを使用してrootReducer()
関数の記述を完成させてください。counterReducer
をcount
というキーに割り当て、authReducer
をauth
というキーに割り当ててください。
解答としては下記のようになりました。
ストアにアクションデータを送信する
ストアにアクションデータを送信するには、
dispatchにアクションを乗せて送信するのでした。
そのアクションが届いてから、reducerでstoreの変更をして新しいオブジェクトを生成しました。
下記のような課題がありました。
コードエディターで、基本的な notesReducer() と addNoteText() アクションクリエイターが定義されています。 action オブジェクトを返すように addNoteText() 関数の本体を完成させてください。 オブジェクトには、ADD_NOTE という値を持つ type プロパティを含める必要があり、アクションクリエイターに渡される note データが設定された text プロパティも含める必要があります。 アクションクリエイターを呼び出すときには、オブジェクトに対してアクセスできる具体的なノート情報を渡します。
次に、notesReducer() の switch ステートメントの記述を完成させてください。 addNoteText() のアクションを処理する case を追加する必要があります。 この case は、タイプ ADD_NOTE のアクションが存在する場合にトリガーする必要があり、action を受信したときに新しい state として text プロパティを返す必要があります。
アクションはコードの最後でディスパッチされます。 記述を終えたら、コードを実行してコンソールを確認してください。 以上のコードだけで、アクション固有のデータをストアに送信して、ストアの state を更新するときに使用することができます。
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/send-action-data-to-the-store
解答はこのようになりました。
ミドルウェアを使用して非同期アクションを処理する
Reduxでも非同期のエンドポイントなどを呼び出すことがあるようです。
Redux では、この目的のために設計されたミドルウェアが用意されていて、Redux Thunk ミドルウェアと呼ばれているようです。
使用方法としては、
Redux.applyMiddleware()
どのような動作をするのか、
Reduxのミドルウェアは、アクションがディスパッチされるときに、アクションと新しい状態の中間に割り込むことができます。これにより、非同期処理やロギング、エラーハンドリングなどの追加の機能をアプリケーションに統合することができます。
ロギング:アプリケーション内での動作や状態を記録する。
エラーハンドリング:アプリケーションがエラーを適切に処理する仕組み。
下記のような課題がありました。
https://www.freecodecamp.org/japanese/learn/front-end-development-libraries/redux/use-middleware-to-handle-asynchronous-actions
handleAsync()
アクションクリエイターに両方のディスパッチを記述してください。requestingData()
をsetTimeout()
(API 呼び出しのシミュレーション) の前でディスパッチしてください。 次に、データを受信 (する真似を) した後で、receivedData()
アクションをディスパッチし、このデータを渡してください。 これで、Redux での非同期アクションの処理方法がわかりました。 他はすべて以前と同じように動作します。
今回の内容では、Reduxでの主な原則を学ぶことができました。
ただ、Reduxも最近では、reducerやactionを定義するときに、
createSlice()
という関数を用いてreducerやactionを1つのオブジェクトにまとめて定義できるようになっているそうです。(この辺りもまた記事にできたらなと思っています。)
今日はここまでです〜。