Vue.js+Vuexはそれなりに趣味で使ってきたけど、
React+Reduxは入門レベルの私がReduxを触ってみて「Vuexより複雑に見える@@」と感じたので、
Reduxについて習得したことを今後のためにここにメモしていこうと思う。
2022年12月25日現在勉強中、じゃんじゃん追記していく予定。
Reduxとは
フロントエンドアプリの全体的な状態管理を行うためのフレームワーク。
複数のページや複数の画面要素で必要となるデータを「ストア」と呼ばれるオブジェクトで管理し、ストア内のデータは「アクション」と呼ばれる専用のトリガによってのみ更新可能とするデザインパターン(Fluxパターンと似ている)を採っている。
この仕組みにより、画面内の任意の要素(コンポーネント)から同一のデータへのアクセスが容易となる。
この仕組みが無い場合、コンポーネント間でバケツリレーのようにデータの受け渡しをせざるを得ない状況が発生することがあり、データ構造等の変更に対する保守が鬼のように大変になってしまう。
ReduxはReactと併用されることが多いが、他との併用も可とされる。
2022年12月現在、Reduxを直接利用するのではなく、Redux Toolkitを用いて利用することが公式に推奨されている。
Redux Toolkitとは
一般に「複雑」と言われるReduxの導入・利用にかかる作業を簡素化するためのライブラリ。
用語
Action
画面からストアに対して何かしら(データ更新など)のリクエストを投げたいときに使う唯一のもの。
次の例の形式のオブジェクトとして定義する。type(文字列)は定義必須だが、payloadは任意。
const addTodoAction = {
type: 'todos/todoAdded',
payload: 'Buy milk'
}
ここで、typeにスラッシュで区切った文字列を定義しているが、慣例として次のようにする。
- スラッシュの左側(例ではtodos):機能、カテゴリを自分なりに記載する。
- スラッシュの右側(例ではtodoAdded):イベント名を自分なりに記載する。
payloadは、任意の型の情報を定義して良い。
Action Creator
Actionオブジェクトを返す関数。
例えば次のようなAction Creatorを定義しておくと、payloadに好きな値を指定した type: ‘todos/todoAdded’ のアクションを簡単に生成できるようになる。
const addTodo = text => {
return {
type: 'todos/todoAdded',
payload: text
}
}
state
ストアで管理するデータを指す言葉。
アプリの「状態」とも呼べるため、このようなネーミングになっている。
ストア1つにつきstate1つ。
Reducer
Actionのtypeに応じて呼び出される関数。
引数としてstateとActionを受け取り、その両者の情報のみを元にstateの新たな値を返す。
従って、以下はNGとされる。
- 戻り値がstateとAction以外に依存する。
- Reducer内部で乱数を生成し、それが戻り値の決定に影響する。
- 非同期処理により呼び出す状況によって戻り値が変わる。
Reducerの実装は一般に次の流れとなる。
- 引数で受け取ったActionのtypeを参照し、このReducerが担当するActionかどうか判定する。
- 担当するActionだった場合、stateのコピーを生成し、コピーを更新し、更新したコピーを新たなstateの値として返す。
- 担当するActionではなかった場合、現状のstateをそのまま返す。
Store
ストア。
アプリ全体から参照できるデータの置き場所となるオブジェクト。
Dispatch
ストアが持つメソッド。dispatchメソッド。
このメソッドに対して次の要領でActionを渡すことでストアに対してデータ更新をリクエストできる。
store.dispatch({ type: 'counter/increment' })
ここで、先ほど出てきたAction Creatorを使うと、次のようにも書ける。dispatch文が少しすっきり書けるようになった。
const increment = () => {
return {
type: 'counter/increment'
}
}
store.dispatch(increment())
getState
ストアが持つメソッド。現在のstateを取得できる。
Selector
stateの中の特定の部分を抽出したいときに定義し使用する関数。
次のようにselectCounterValue関数をSelectorとして定義しておけば、ストアからstateの範囲を絞り込んでデータが取得できる。
const selectCounterValue = state => state.value
const currentValue = selectCounterValue(store.getState())
React+Reduxのプロジェクト構成手順
TBD