LoginSignup
9

More than 5 years have passed since last update.

Redux の reducer を非同期取れるようにしてみた

Last updated at Posted at 2017-03-30

Reduxへの理解を深めるために、コードをいじってみて、どれぐらい大変か確認してみた。
実験的なものなので、プロダクションでは使わないように

発想

主にここ
https://gist.github.com/mizchi/d4a8455ef56a7adc123a388b3a5eaaaf

redux の reducer は非同期も取りたい。具体的には f(state: State, action: Action): State ではなく f(state: State, action: Action): State | Promise<T> としたい

できたもの

reducer が async/await で(Promiseで)書ける。

export default async (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'INCREMENT_ASYNC':
      await new Promise(done => {
        setTimeout(done, 500)
      })
      return await Promise.resolve(state + 1)
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

実際の挙動。

感想

実際に作ってみると、ひたすら async await キーワードが伝搬していく感じだった

互換のものを作ろうとすると、どこまで仕様で、どこから仕様じゃないか理解してないと、この先書ける気がしなかった。似て非なるものを作るのは簡単。middleware を非互換に、subscribe を書き直すといい。

⋊> ~/p/redux on master  yarn test
 PASS  test/typescript.spec.js
 PASS  test/createStore.spec.js
 PASS  test/combineReducers.spec.js
 PASS  test/applyMiddleware.spec.js
 PASS  test/bindActionCreators.spec.js
 PASS  test/compose.spec.js
 PASS  test/utils/warning.spec.js

Test Suites: 7 passed, 7 total
Tests:       16 skipped, 51 passed, 67 total
Snapshots:   0 total
Time:        5.181s
Ran all test suites.

非同期APIを取ることでそもそもテスト側を障る必要もあり、互換というわけではない。
全然関係ないが、 jest のアサーションが非同期に対して貧弱すぎてクソという感想をもった。

できなかったこと

  • オリジナルの Middleware と互換にしたかったが、実行順の関係で、非同期用に書き直さないといけないとたぶんダメ。src/compose.js を読み切ればなんかできるかも。
  • subscribe されたものが発火する順番が、オリジナルと変わってしまっている。

そもそも middleware 使わなくていいように reducer で非同期取れるようにしてるんだから、Middlewareは redux-logger が動くぐらいでいいのかもしれない。subscribe はなんとかしたい。

この辺で時間切れ

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
9