[Redux] actionがどのようにserializer, stateを探し当てるか

2 min読了の目安(約2600字TECH技術記事

reduxの勉強をしていて、action => reducer => store => componentの流れは理解できたのですが、
実際に実装してみるとこんがらがってしまったので、1つ1つ流れをまとめておきます

1. 各reducerがcombineReducersによってroot.reducerに関連づけられる

// root.reducer.js
import { combineReducers } from 'redux'
import userReducer from '../redux/user/user.reducer'
import cartReducer from '../redux/cart/cart.reducer'

const rootReducer = combineReducers({
  user: userReducer,
  cart: cartReducer
})

このような関連ができる
user.reducer, cart.reducer => root.reducer

※これからuser.reducer, cart.reducerなどはまとめてeach_reducerと呼びます


2. root.reducerがstoreに関連づけられる

// store.js
import { createStore } from 'redux'
import rootReducer from '../redux/root.reducer'

const store = createStore(rootReducer)

このような関連ができる
root.reducer => store


3. storeがApp全体に関連づけられる

// index.js
import { Provider } from 'react-redux'
import store from '../redux/store'

<Provider store={store}>
  <App />
</Provider>

このような関連ができる
App => store => root.reducer => each_reducer

ここまででApp全体(各Component)からeach_reducerにアクセス可能な関連付けができる

しかし、ここではまだ各storeのactionsが関連づけられていない
ではどこで関連づけるか?



A. そのstoreのstate, actionを呼び出したいComponentにおいて、actionとそのComponentを関連付ける(connectを使用)


既にApp(各Component)からstore, reducerまでは関連づいているので、
actionとComponentを関連付ける


4. actionとComponentを関連づける

// header.component.jsx
import { connect } from 'redux'
import { toggleCartHidden } from '../../cart/cart.actions/'

// 3. connectしたので、props.hidden, props.toggleCartHiddenで呼び出せる
const Header = (props) => (
  <div>...</div>
)

// 1. ここには呼び出したいstateを登録する
const mapStateToProps = ({ cart }) => ({
  hidden: cart.state.hidden
})

// 1. ここには呼び出したいactionを登録する
const mapDispatchToProps = (dispatch) => ({
  // toggleCartHiddenはcart.actionsのアクションなので、
  // cart.reducerの引数actionに渡される
  
  toggleCartHidden: () => dispatch(toggleCartHidden)
})

// 2. 上記で登録したstateやactionをこのComponentに関連づけて、
// propsから取得できるようにする
export default connect(mapStateToProps, mapDispatchToProps)(Header)

これにより、下記のような関連付けができる
action => Component => App => store => root.reducer => each_reducer

これがactionが呼ばれてからreducerを探し当てるまでの流れ

cartのstateが参照されたらstoreから探し当てるし、cartのactionが呼ばれたらcart.reducerを探し当てて、その引数(action)にわたす


まとめ(actionがreducerを探し当てるまで)

action => Component => App => store => root.reducer => each_reducer

どのような関数を使ってお互いを接続しているかも示すと、下記のようになる

ex) action => (connect) => Component  
=> 「actionとComponentをconnectを使って接続している」  

action => (connect) => Component => App => (Provider) => store  
=> (createStore) => root.reducer => (combineReducers) => each_reducer