Reduxとは
Reduxは、アプリケーション全体の状態を管理および更新するためのパターンとライブラリです。
UIは「Action」と呼ばれるイベントをトリガーして何が起こったかを伝え、それに応じて「Reducer」と呼ばれる別の更新ロジックが状態を更新します。
Reduxは、アプリケーション全体で使用する必要がある状態を一元的に保存する役割を果たし、状態が予測可能な方法でのみ更新されるようにルールが定められています。
どういう時にReduxを使うべきか
グローバルな状態を管理する時に役に立ちます。
グローバルな状態=アプリケーション全体で管理が必要になる状態を指します。
特に状態が多い、更新頻度が多い、更新ロジックが複雑になる場合はReduxを利用するのが良いかと思います!
最新の Redux については、 Redux Toolkitを使うのが推奨されています。
https://redux.js.org/tutorials/fundamentals/part-1-overview#redux-toolkit
Reduxの仕組みを理解する
ざっくり登場人物・用語
- Store: グローバル状態を保管している倉庫のようなもの
- Reducer: 倉庫の番人。この人しか倉庫は弄れない
- Action: 倉庫の番人(Reducer)に伝える指示。あの状態をこれに変えといて〜みたいな
- Dispatch: 倉庫(の番人)に指示(Action)を伝えること
- UI: 実際のユーザーがアプリ上で触る箇所。触った結果ActionCreaterからActionが発行され、番人(Reducer)に送られる
イメージ図としては公式サイトの図が一番分かりやすいかと思います!
https://redux.js.org/tutorials/fundamentals/part-1-overview#data-flow
もう少し詳しく
Store
アプリケーションのグローバル状態を保持するコンテナです。
Storeは、単純なグローバルオブジェクトとは異なる、いくつかの特別な機能を備えた JavaScript オブジェクトです。
原則として、Store内に保存されている状態を「直接」変更したりしてはいけません。
状態の更新を引き起こす唯一の方法は 「どの状態をどう変更するのか」を含んだActionと呼ばれるオブジェクトを伝えることです。
Reducer
関数です。
現在の状態(state)と、「どの状態をどう変更するのか」を含んだActionと呼ばれるオブジェクトの2つの引数を受け取ります。
その後Reducerは現在のStateとActionを元に更新した新しいstateを返却します。
下記例だとActionオブジェクトのtypeが'counter/incremented'の場合は現在の状態に+1を、'counter/decremented'の場合は現在の状態に-1した値を新しい状態とし、現在の状態と新しい状態の両方を返しています。
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'counter/incremented':
return { ...state, value: state.value + 1 }
case 'counter/decremented':
return { ...state, value: state.value - 1 }
default:
return state
}
}
ちなみに、Reduxアプリの起動時にはまだ状態がないので、initialStateをデフォルト値として指定します。
Action
先述の通りオブジェクトです。typeと他プロパティを持ちます。
他プロパティのところは自由に指定できます
{
type: "UpdateStateA",
payload: testStateA
}
ReducerはAction.typeを見て更新処理を分岐し、必要に応じて他プロパティを使って新しい状態を生み出します。
Redux Toolkit (RTK) だと ActionCreator が自動生成されるため、Actionはそこで生成することができます。
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
Dispatch
作成されたActionをStoreに伝えることを指します。
// ボタンをクリックしたら、storeに{ type: 'counter/incremented' }のアクションを伝える
document.getElementById('increment').addEventListener('click', function () {
store.dispatch({ type: 'counter/incremented' })
})
Actionを受け取ったstoreはreducer関数を呼び出し、新しい状態を生成します。
その後、storeの値を更新し、UI側に新しい状態を返すことでUI側に反映することができます。
再掲
ここまで読んでいただいた状態で再度公式サイトの図を見ると理解が深まるのではないでしょうか!
https://redux.js.org/tutorials/fundamentals/part-1-overview#data-flow
終わりに
最後まで読んでいただきありがとうございました!
Reduxは最初登場人物が多く、覚えないといけない概念が多いように感じで毛嫌いしていた時期もありましたが、
公式サイトをはじめ色々読んでみると意外とシンプルな仕組みになっているかと思います!
参考