Reactに引き続きReduxのキャッチアップが必要になりました... 日本語のドキュメントを読んで必要そうなとこだけまとめた自分用メモです。 間違い、分かりにくい部分がたくさんあるはずです。 Redux自体少し古い技術っぽいので参考にならない部分が大いにあると思います。
Redux/Redux Toolkit
Redux、Redux Toolkitについて。
- ReduxはJavaScriptアプリの予測可能な状態コンテナ
- Reduxは状態管理ライブラリ
- ストア
- アクション
- リデューサー
npm
Redux Toolkit
- Reduxのサポートツール
- npmパッケージ
Fluxが元になっている
要点
Reduxの概要。
- Reactの
state
をStoreの1つのオブジェクトツリーで保持 - 状態ツリーはActionで変化できる
Actionへの指示をReducerに書く? *状態オブジェクトは書き換えずに、状態が変化した新しいオブジェクトを作成する
状態の変化に応じてUIを更新するために
subscribe()
を使うsubscribe()
を直接呼び出すことは少ないReact Redux
ライブラリを使ってsubscribe()
を呼び出す
状態を変化させるにはActionをDispatch(送信)すること
- Action内でReducerを書く
- 書いたActionをDispatchする
- 状態が変化する
変更の大元になるのは1つのReduce、1つのStoreだけ
- 大元のReducerから子Reducerを作ることはある
- Reactの仮想DOMみたいなもん
- 大元のReducerから子Reducerを作ることはある
モチベーション
Reduxがなぜ開発されたのか。
- Railsでのデータの更新、ReactでのUI上での見た目の変化を切り離すためにあるっぽい?
核となるコンセプト
Reduxの考え方について。
Actionは何が起きたのかを記述するだけのJavaScriptオブジェクト
Actionは
何が
、どう
変化したのかが記述されている- Actionを見れば変化の詳細が分かる
- Actionの最後に
Reducer
関数を記述する- 引き数は
今の状態
、Action
、次の状態
の3つ- UIのパーツ毎に関数が増えていくっぽい
- 引き数は
ReducerがActionの中に書いた関数を呼び出すっぽい
- Reduxのコードの90%はただのJavaScript
3つの原則
Storeについて。
アプリケーションの状態は1つのStoreの中の1つのオブジェクトツリーで保持される
- オブジェクトツリーを状態ツリーとも呼ぶ
- デバッグ時は状態ツリーを調査すればok
console.log(store.getState())
でStoreの状態が取得できる?
状態は読み込み専用
- 状態を表現する状態ツリーは書き換えない
- 状態を変化させるにはActionを送信(Dispatch)することのみ
Reducerはただの関数
Reducerの引数は
今の状態
、Action
、次の状態
- 「こうなっているのを、〇〇を使って、こうしたい」みたい感じ
- 前の状態を変更するのではなく、次の状態を新たに作って返す(新しいオブジェクト)
ReducerでActionを呼び出す順番の制御を行う
- 状態ツリー(仮想DOMみたいな)の要素毎に子Reducerを追加していく
Action
Actionについて。
- Actionに状態変化の情報が書いてある
- ActionはアプリケーションからStoreに送られるデータ
- StoreはActionのデータだけを参照する
store.dispatch()
でActionをStoreに送るActionは単なるJavaScriptオブジェクト
Actionは必ず
type
プロパティを持つtype
プロパティが状態を変化させるActionのタイプを示すtype
は文字列の定数で定義される
Actionの
type
を別モジュールで使う場合はimport
を使うimport {ADD_TODO, REMOVE_TODO} from '../actionTypes'
type
を定数で定義していることで複数のファイルでも動作できるのかも?
Action内には
type
に加えて独自の項目(プロパティ)を追加できるActionで渡すデータはできるだけ小さく(少なく)する
Actionを作る関数を
Actionクリエイター
と呼ぶ- Actionオブジェクトを返す関数?
Actionを送信するDispatchを行うには
dispatch()
関数を使う- 引数にActionクリエイターの関数を渡す
自動でDispatchするActionクリエイターを
バウンドActionクリエイター
と呼ぶdispatch()
関数の呼び出しはstore.dispatch()
でStoreから直接行うreact-redux
のconnect()
で行うことが多い
react-redux
とはReactコンポーネントとReduxストアを結びつけるライブラリ- ReactコンポーネントとReduxストアの結合が簡単になる
react-redux
の主な機能import
とexport
を使って関数、変数を複数のモジュールで使用するimport
はfrom
でインポート先のパスを記述する
Reducer
Reducerについて。
- Reducerがイベントに反応して状態を変化させる
- アプリケーションの状態を1つのオブジェクトとして保持している
- Railsから送信されるデータとUIの状態をプロパティを使って分けて管理する
{ visibilityFilter: 'SHOW_ALL', todos: [ { text: 'Consider using Redux', //UIの状態 completed: true, //データの状態 }, { text: 'Keep all state in a single tree', //UIの状態 completed: false //データの状態 } ] }
- Reducerファイル内プロパティのネストは深くしない
- ネストを浅くしてオブジェクトのidでアクセスした方が管理しやすい
- Reducerは
前の状態
、Action
、次の状態
を引数にとり、次の状態
を返すJavaScriptの関数 Reducerは内部的に
Array.prototype.reducer
を呼び出しているArray.prototype.reducer
とは配列の合計値を出せるRubyのeachの応用みたいなやつ
Reducerでやってはいけないこと
- 引数を変更する
- 関数の呼び出し
- 外部の処理(API等)の実行
Reducerは
Action
で次の状態
を振り分けるコントローラーみたいなものReducerはJavaScriptの
Object.assign
メソッドでAction
元にした次の状態
のオブジェクトを作成する- JavaScriptの
Object.assign
メソッドは新しいオブジェクトを作成するメソッド
- JavaScriptの
combineReducers()
関数は複数のReducerを結合して1つのReducer関数を作るもの
Store
Storeについて。
Store: Action、Reducerをまとめるオブジェクト
- Action: イベント
- Reducer: Actionを起点に状態を変化させる
Storeの役割
- アプリケーションの状態のを保持
getState()
で状態の変更を許可するdispatch(action)
で状態の更新を許可するsubscribe(listener)
で状態の変更を検知した時に発動するメソッドを登録する
Storeは必ず1つ
状態で処理を分けたい時はReducerで処理を分岐させる
Storeの作成は
combineReducers()
で複数のReducerを1つにまとめ、createStore()
に渡すだけ
Storeの初期状態を設定するには
createStore()
の2つ目の引数に初期状態のstateを渡す
データフロー
Reduxのデータの流れについて。
Reduxのデータの流れは一方向
データのライフサイクル
store.dispatch
を呼び出しAction(イベント)を送る- ReducerがActionを元に
次の状態
を呼び出す(新しいオブジェクトを作成) combineReducers()
で複数のReducerを1つにまとめる(この時点で状態変更は保存されている)- 1つにまとめられたReducerを元に
store.getState
で現在の状態を取得する React Redux
を使っている場合はcomponent.setState(newState)
で自動で新しい状態を反映する
感想
Reactに続き、Reduxも難解です... じっくり腰を据えて学んでいきたいところですが今は概要が掴めたのでとりあえずokにしときます。 新しいことや分からないことを直視するのはなかなか大変ですが、プログラミングってそもそもそういうモノだったなぁと思い出すきっかけになりました。 そもそも人はやれる事しかやれないので焦らず地道に進んでいきます!
参照
Redux - A predictable state container for JavaScript apps. | Redux