Reduxの日本語ドキュメントの自分用メモ

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(送信)すること

    1. Action内でReducerを書く
    2. 書いたActionをDispatchする
    3. 状態が変化する
  • 変更の大元になるのは1つのReduce、1つのStoreだけ

    • 大元のReducerから子Reducerを作ることはある
      • Reactの仮想DOMみたいなもん

モチベーション

Reduxがなぜ開発されたのか。

  • Railsでのデータの更新、ReactでのUI上での見た目の変化を切り離すためにあるっぽい?
    • Railsから送られるJSONの情報を使ってReactがUIを変化させることで複雑性が増すらしい
    • Railsから送られるJSONの情報をReduxがStoreに保持、保持した情報を元に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-reduxconnect() で行うことが多い
  • react-redux とはReactコンポーネントとReduxストアを結びつけるライブラリ

  • react-redux の主な機能

    • Provider コンポーネント
    • connect 関数
      • ReactコンポーネントをReduxストアに送信
      • ReactコンポーネントがReduxストアの状態を参照し、必要なデータをpropsとして取得する
      • ActionをStoreに送信(Dispatch)することもできる
        • mapStateToProps: ReactがReduxからデータを取得
        • mapDispatchToProps: ReactからReduxへのデータの送信
  • importexport を使って関数、変数を複数のモジュールで使用する

    • importfrom でインポート先のパスを記述する

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はJavaScriptObject.assign メソッドでAction 元にした次の状態 のオブジェクトを作成する

    • JavaScriptObject.assign メソッドは新しいオブジェクトを作成するメソッド
  • 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のデータの流れは一方向

  • データのライフサイクル

    1. store.dispatchを呼び出しAction(イベント)を送る
    2. ReducerがActionを元に次の状態 を呼び出す(新しいオブジェクトを作成)
    3. combineReducers() で複数のReducerを1つにまとめる(この時点で状態変更は保存されている)
    4. 1つにまとめられたReducerを元にstore.getState で現在の状態を取得する
    5. React Redux を使っている場合はcomponent.setState(newState) で自動で新しい状態を反映する

感想

Reactに続き、Reduxも難解です... じっくり腰を据えて学んでいきたいところですが今は概要が掴めたのでとりあえずokにしときます。 新しいことや分からないことを直視するのはなかなか大変ですが、プログラミングってそもそもそういうモノだったなぁと思い出すきっかけになりました。 そもそも人はやれる事しかやれないので焦らず地道に進んでいきます!

参照

Redux - A predictable state container for JavaScript apps. | Redux

はじめに · Redux