本サイトではアフィリエイト広告を利用しています。
Reduxについての概要2020/02/14

Reduxについての概要

以前からReact/React NativeにてReduxを利用したアプリを作成しています。

Reduxの概念について説明する機会があったので、簡単にですがまとめておきます。 いったんキーワードベースでの解説としいます。サンプルコード等は少なくしました。

基本的にReduxはstateの管理を1つのストアで集約的に管理するものです。 これを使うことでコンポーネントから一元管理されたstateへアクセスできるようになります。 使わない場合はprops等でやり取りすることになりますね。

概要

  • ドキュメント
  • Store
  • Actions
  • Reducer
  • Connect

ドキュメント

https://redux.js.org/introduction/getting-started
reduxのドキュメントです。基本これのチュートリアルを順番に読んでいくことで理解が進みます。

https://react-redux.js.org/introduction/basic-tutorial
reduxをreactで使うためのライブラリーです。reduxはreact以外のフレームワークでも使えるようで、それぞれに対応したライブラリーを使うことがおすすめされています。 reactに対してはこのreact-reduxが公式でもオススメとされています。

Store

ReduxではアプリケーションのすべてのStateをひとつのオブジェクト「Store」にて管理する。

StoreはgetStoreによりデータにアクセスが可能で、dispatchによってデータの更新を行う。 subscribeによってリスナーを登録することもでき、解除もできる。

データを分割したい場合、Storeを複数つくるのではなくReducerの分割を行います。

アプリケーションに対してStoreは1つという決まり。

このStoreにてデータを一元管理すること・できることがReduxの肝心なところ。

Actions

Storeに情報を渡すためのオブジェクト。

オブジェクトでありプロパティとして「type」が必要。 typeの値には定数文字列が推奨されており、文字列リテラルでも良い。 「ActionTypes」としてファイルを切り出して定義しておくのがオススメ。

payloadとしてストアに渡されるデータをまとめて定義することもある。

// Action 純粋なオブジェクト
const addTodoAction = {
  type: ADD_TODO,
  payload: {
    id: ++nextTodoId,
    content
  }
}
;

ActionCreator

引数を受け取りActionを返すメソッド。 これを「dispatch」でStoreに渡すことでStoreの更新を行う。

// これは引数を受けとり、Actionを返すのでActionCreator
export const addTodo = content => ({
  type: ADD_TODO,
  payload: {
    id: ++nextTodoId,
    content
  }
});

Reducer

Storeへ渡されるActionに応じて、State更新の内容を定義しておく。
Actionの「type」によって更新内容を切り分ける。

Reducerは前のStateとActionを受け取り、次のstateを返す。 Stateに書き込むのではなく別のオブジェクトを返す。したがって、Stateを直接書き換えてはいけない。 前のStateの中身を展開したものと、更新するパラメータをオブジェクトにしてまとめて返す。すなわち更新後のState。

意図せず未定義のアクションが渡された場合は前のStateをそのまま返す。
一番最初はStateが空なはずなので、Stateの初期値を与えておく。

Reducerでやってはいけない3つのこと

  • 引数に与えられたものを直接書き換えてはいけない
    書き換えるのではなく、新しいStateをつくって返す
  • APIの呼び出しやルーティング処理をしてはいけない
  • 純粋でない関数を呼んではいけない
    dateとかrandomとか

CombineReducer

データ定義や関連するドメインなどで分割して子Reducerを作っておき、合成して親Reducerとして扱うと良い。 Stateの一部を管理するような子Reducerを複数作成して、CombineReducerにて結合するのが良い。

動作としてはDispatchにActionを渡すと、全ての子ReducerにActionを渡して帰ってきた新しいStateを結合しているらしい?。

export default combineReducers({ todos, visibilityFilter });

Connect

Connectを使ってコンポーネントをラップすることでコンテナ化する。 こうしてコンテナ化することで、Storeからのデータ取得やdispatchによるデータ更新を可能にする。

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Component);

mapStateToProps

Connectの1つ目の引数。
Storeにアクセスしてデータを取得する処理を行い、stateをコンポーネントのpropsに渡します。 Storeから必要なデータを取得・変換・編集してコンポーネントのpropsへ渡すことが目的です。

基本的にReduxはStoreに何らかの更新があると、データが再取得され再レンダリングの対象になるようです。

このメソッドを定義しなかった場合はStoreがコンポーネントのpropsに渡される?ようです。 nullとかを渡せば、更新不要なコンポーネントとして定義できるかな。

mapDispatchToProps

Connectの2つ目の引数。
Storeにdispatchして更新するための処理をコンポーネントのpropsに渡します。

コンポーネント内でdispatchを実行してもいいのですが、こちらで定義しておくことも出来ます。 定義しなかった場合はdispatchがコンポーネントに渡されるので、コンポーネント内でpropsのdispatchを実行します。

おわりに

Reduxは理解するのに時間がかかるという話を聞きますが、それほどで難しいものではないです。 時間を取ってドキュメントを見れば簡単に理解できます。大きなフレームワークではなく小さなライブラリーですので。

ドキュメントが英語なのでとっつきにくいですが、勉強してみるとおもしろい仕組みです。 コンポーネント間で正しくデータを管理して渡せば、Reduxが無くても実装は可能です。しかし、Reduxを選択肢として使えるととても便利です。

React・React Nativeで実装するに当たって、主要ライブラリの1つですのでしっかり身につけておきたいです。

  • このエントリーをはてなブックマークに追加
prev
next