強まっていこう

あっちゃこっちゃへ強まっていくためのブログです。

結局 redux-thunk って何なのマジ?超ムカつくんですけど

ググってもろくな情報が出ずイライラしている諸氏に送るシリーズ。

redux-thunk の使用を推奨しているわけでは無いのであしからず。
無邪気キッズがインタネッツの情報に踊らされた結果導入->破綻しその尻拭いをする事になったおっちゃん達向け。
こちとらイライラをモチベとして書いているので、React ファンボーイは気分を害する恐れアリ。そっ閉じ願う。

で、こいつは何か?

Redux で async やるためのもの。そう、それだけ。バカ丸出し。

wolfbash.hateblo.jp

上記エントリーで書いたコードの async 部分を thunk に変えたものを示す。

import axios from 'axios'
import React from 'react'
import { createStore, applyMiddleware } from 'redux'
import { Provider, connect } from 'react-redux'
import thunk from 'redux-thunk'

const gStatus = {
  time: '---',
}

const Main = connect()(props => {
  return (<div>
    <Input />
    <Display />
  </div>)
})

const Display = connect(status => status)(props => {
  return (<div>
    <p>Time: {props.time}</p>
  </div>)
})

const Input = connect(
  state => state,
  dispatch => {
    return {
      // store の dispatch を直接ひっぱたく方法
      getTime: arg => {
        axios.get('https://ntp-a1.nict.go.jp/cgi-bin/time').then(res => {
          store.dispatch({
            type: 'getTime',
            payload: arg + res.data
          })
        })
      },
      // thunk 使うと store.dispatch に関数が渡せるようになり dispatch を引数で渡しつつ叩いてくる
      // なので、こいつで dispatch を引数で受ける関数を返してやるようにすれば良いと言う話
      getTimeThunk: arg => {
        return _dispatch => {
          axios.get('https://ntp-a1.nict.go.jp/cgi-bin/time').then(res => {
            _dispatch({
              type: 'getTime',
              payload: arg + res.data
            })
          })
        }
      },
      // まともな方法
      getTimeAsync: async (arg) => {
        const res = await axios.get('https://ntp-a1.nict.go.jp/cgi-bin/time')
        dispatch({
          type: 'getTime',
          payload: arg + res.data
        })
      }
    }
  }
)(props => {
  let input = ''
  return (<div>
    <button onClick={() => props.getTime('NOW=')}>getTime</button>
    <button onClick={() => store.dispatch(props.getTimeThunk('NOW='))}>getTime(Thunk)</button>
    <button onClick={() => props.getTimeAsync('NOW=')}>getTime(Async)</button>
  </div>)
})

const store = createStore((state, action) => {
  switch (action.type) {
    case 'getTime':
      return { ...state, time: action.payload }
    default:
      return state
  }
}, gStatus, applyMiddleware(thunk)) // tunk 使うために applyMiddleware(tunk) を渡してやる

export default (props) => {
  return <Provider store={store}><Main /></Provider>
}

コメントで書いているが、一応説明。

getTime は store.dispatch を直接叩く方法。これを redux-thunk を使うと、getTimeThunk のように書ける。そう書けるからと言って何が嬉しいか?特に何も嬉しくは無い。

まともな方法として書いている getTimeAsync で書くのが一番。昔は Redux で async を store.dispatch を直接叩く方法でしか扱えなかったから必要なものっぽい雰囲気。

完全なバッドノウハウ。RIP