useDispatchでredux-thunkを使ったらthenができない件の解決法 (Typescript)


redux-thunkのthen

たとえばTodo listに一つアイテムを追加・編集・削除した後、
改めてサーバーにRetrieve Listをしたい場合ありますよね。
redux-thunkはこういう感じができます:


const createActionCreator = (item) => {
  return dispatch => {
    return axios
      .post('api/todo', item)
      .then(response => {...}) // 割愛します
  }
}

const retrieveActionCreator = () => {
  return dispatch => {
    return axios
      .get('api/todo')
      .then(response => {...}) // 割愛します
  }
}

// どこかで
dispatch(createActionCreator(newItem))
  .then(() => {
    dispatch(retrieveActionCreator())
  })

// ちなみに
dispatch(createActionCreator(newItem))
dispatch(retrieveActionCreator())
// こういう風に書くと、両者ともAsync Callなのでどれが先に完成するのかは保証できませんので。
// 上みたいにthenを使う必要はあります。

useDispatchのdispatchを使うとできなくなる

言語:Typescript
JSだと多分エラー出ないですね。

import { useDispatch } from 'react-redux';

const dispatch = useDispatch()

dispatch(createActionCreator(newItem))
  .then(() => { // このthenでエラーが出ます
    dispatch(retrieveActionCreator())
  })

実例:

Property 'then' does not exist on type '...' みたいなエラーが出ますね。
typeactionCreatorreturn typeなので人によっては違いますが。

解決法

多分react-reduxがredux-thunkのdispatchの型を知らないので、type checkが通ってない気がします。

storeHelper.ts

import { ThunkDispatch } from 'redux-thunk';
import { Action } from 'redux';
import { useDispatch } from 'react-redux';

import { SystemState } from 'features/systemState';
// このSystemStateは自分で定義したReduxのStore構成、詳細は割愛します
// Todo Listだと { items: {name: string ,finished: boolean}[] } みたいな

export type ReduxDispatch = ThunkDispatch<SystemState, any, Action>;
export function useReduxDispatch(): ReduxDispatch {
  return useDispatch<ReduxDispatch>();
}

元のファイルで:

import { useReduxDispatch } from './storeHelper'

const dispatch = useReduxDispatch()
dispatch(createActionCreator(newItem))
  .then(() => { // できました
    dispatch(retrieveActionCreator())
  })

終わりに

ご指摘がございましたら、コメントを頂けるとありがたいです。
もしお役に立ちましたらいいねを貰えると嬉しいです。