LoginSignup
17
11

More than 5 years have passed since last update.

Reduxの基本的な仕組み

Posted at

Reduxとは?

Reduxは状態を一元管理してくれるやつ。Reactはそもそも状態を管理しやすくなるようにしているので、いつでも使う必要はない。一元管理したくなったら使う。ドキュメントには大量の説明とチュートリアルやサンプルがある。

Reduxの仕組み

Reduxは状態(state)を一つのstoreに保存し一元管理します。createStore()でstoreがつくれます。createStore()には引数としてリデューサー(reducer)というのを渡します。

let store = createStore(reducer)

reducerとういのは、各アクションとstateを結びつける関数です。具体的には、現在のstateと、アクションを引数にとり、次のstateを返す関数です。

アクションというのは、stateが変わる要因となるアプリケーション上の挙動です(moneyというstateが100のときに、「お金を10支払った」とういアクションがあれば、moneyは90になるべきです)。具体的には下記のようになります。

{ type: 'PAY_MONEY', price: 10 }

reducerは、アクションが発生した場合に、どのstateをどのように変化させるかを規定する関数です。また、reducerには、stateの初期値も登録します。

const iniState = {
  money: 100
}
function reducer(state = iniState, action) {
  switch(action.type) {
    case 'PAY_MONEY':
      return Object.assign({}, state, {
        money: state.money - action.price
      })
    default:
      return state
  }
}

このreducerをstoreに渡すことで、storeは、全てのstateとその初期値と、発生しうるアクションと、アクションがあった場合のstateの変化のさせ方を知ります。

状態の取得や、状態の変化のさせ方は、それぞれstoreに対して、store.subscribe()と、store.dispatch()を使います。

store.subscribe()は、アクションがディスパッチされたときに呼び出される関数です。store.subscribe()の中で、store.getState()を使うことで、現状のstateを取得できます。store.subscribe()の戻り値は、subscribeの解除関数です。

store.subscribe(() => console.log(store.getState()))

store.dispatch()は状態を変化させたいときに使い、引数にアクションを渡します。

store.dispatch({ type: 'PAY_MONEY', price: 10 })

実際には、dispacthの引数に直接アクションオブジェクトを渡すのではなく、アクションクリエーター関数を渡します。アクションクリエータ関数は下記のようになります。

function payMoney(price) {
  return { type: 'PAY_MONEY', price }
}

Reduxの簡単な例

redux_sample.js
import { createStore } from 'redux'

//アクションクリエーター
function payMoney(price) {
  return { type: 'PAY_MONEY', price }
}

//Reducer
const iniState = {
  money: 100
}
function reducer(state = iniState, action) {
  switch(action.type) {
    case 'PAY_MONEY':
      return Object.assign({}, state, {
        money: state.money - action.price
      })
    default:
      return state
  }
}

//storeを作成
let store = createStore(reducer)

//subscribe登録
let currentPrice = iniState.money
let unsubscribe = store.subscribe(() => {
  let prevPrice = currentPrice
  currentPrice = store.getState().money
  if(prevPrice !== currentPrice) {
    console.log('changed', prevPrice, 'to', currentPrice)
  } else {
    console.log('no change')
  }
})

//actionをdispatchする
console.log('start pay money')
store.dispatch(payMoney(10))  //100 to 90
store.dispatch(payMoney(20))  //90 to 70
store.dispatch(payMoney(0))   //no change
store.dispatch(payMoney(40))  //70 to 30
let hoge = { type: 'hoge', hoge: 'hoge' }
store.dispatch(hoge)          //no change
store.dispatch(payMoney(10))  //30 to 20

//subscribeを解除
unsubscribe()
console.log('unsubscribed')

store.dispatch(payMoney(10))  //何も表示されない
console.log('finish pay money')
17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11