繁体   English   中英

我的 redux-thunk 调度方法有什么问题? (反应,typescript,TS-2345)

[英]What is wrong with my approach to redux-thunk dispatch? (React, typescript, TS-2345)

我的动作创建者:

// file: redux/contest/actions.ts
import { ThunkAction } from 'redux-thunk'
import { ContestActionTypes, /* ... */ SET_CONTEST_CONFIG } from './types' ;
import { CONFIG_COLL, CONTEST_KEY, database } from '../../database'
import { RootState } from '../store';
/* ... */ 

export const setContestConfig: (arg0: IContestState) => ContestActionTypes =
  (contestState) => ({ type: SET_CONTEST_CONFIG, payload: contestState })

export const loadContestConfig = (): ThunkAction<void, RootState, unknown, ContestActionTypes> =>
  async dispatch => {
    const data = await database.collection(CONFIG_COLL).doc(CONTEST_KEY).get()
    dispatch(setContestConfig(data))
  }

// file: redux/contest/types.ts

/* ... various action structures defined as interface ... */

export type ContestActionTypes = ISerialAction | IStringArrayAction | ITypeOnlyAction | IStringOnlyAction | ISetContestAction 

这部分编译没有任何问题。

现在在我的 index.tsx 我有这个:

import React from 'react';
import ReactDOM from 'react-dom';
import { applyMiddleware, createStore } from 'redux'
import { Provider } from 'react-redux' 
import thunk from 'redux-thunk'
import App from './App';
import { rootReducer } from './redux/store'
import { loadContestConfig, saveContestConfig } from './redux/contest/actions';

const store = createStore( rootReducer, applyMiddleware( thunk ) )
store.dispatch( loadContestConfig() ) // here I want to initialize state from the database
/* ... */

在 index.tsx 的第 11 行( store.dispatch(...) )我收到错误消息 TS-2345

Argument of type 'ThunkAction<void, CombinedState<{ app: AppState; contest: IContestState; }>, unknown, ContestActionTypes>' is not assignable to parameter of type 'ISetStationAction | ISaveAppStateAction | ISerialAction | IStringArrayAction | ITypeOnlyAction | IStringOnlyAction | ISetContestAction'.
  Type 'ThunkAction<void, CombinedState<{ app: AppState; contest: IContestState; }>, unknown, ContestActionTypes>' is missing the following properties from type 'ISetContestAction': type, payload  TS2345

当然,作为 dispatch 传递的动作(在第一个文件中的 function loadContestConfig 中)既有type又有payload ,所以我不知道这里有什么问题。 我按照教程进行了操作,但这无法理解,我只是看不到问题所在。

最后,我能够挖掘解决方案。 有必要指定dispatch类型 function 因为 typescript 无法确定正确的过载。

解决方案亮点

在文件./redux/store.ts中(商店声明)

import { combineReducers } from 'redux' 
import { ThunkDispatch } from 'redux-thunk'
import { AppActionTypes } from './station/types'
import { ContestActionTypes } from './contest/types'
import { stationReducer } from './station/reducers'
import { contestStateReducer } from './contest/reducers'

export const rootReducer = combineReducers({ station: stationReducer, contest: contestStateReducer })  
export type RootState = ReturnType<typeof rootReducer>
export type StoreActionTypes = AppActionTypes | ContestActionTypes 
// the following line is essential - we define proper function type for dispatch with thunk
export type DispatchFunctionType = ThunkDispatch<RootState, undefined, StoreActionTypes>

在文件./index.tsx (React 应用程序主 TSX 文件)

import React from 'react';
import ReactDOM from 'react-dom';
import { applyMiddleware, createStore} from 'redux'
import { Provider } from 'react-redux' 
import thunk from 'redux-thunk'
import App from './App';
import { DispatchFunctionType, rootReducer, RootState } from './redux/store'
import { loadContestConfig } from './redux/contest/actions';
import { loadStation } from './redux/station/actions';

const store = createStore( rootReducer, 
   applyMiddleware<DispatchFunctionType, RootState>( thunk ) ) // <- this is essential
store.dispatch(loadContestConfig()) // here I had TS2345 before, now no more problems 
store.dispatch(loadStation())       //  - dtto -

只要dispatch function 作为参数传递,就必须声明相同的dispatch function 类型。

示例:在文件StationDataModal.tsx

   ...
import { DispatchFunctionType, RootState } from "./redux/store"
   ...

// the following mapping function also caused TS-2345 
// when dispatch type was not declared explicitly
const mapDispatchToProps = ( dispatch: DispatchFunctionType ) => {
  return {
    setContestName: ( name: string ) => {
      dispatch(setContestName( name ))
      dispatch(saveContestConfig())
    },
    setStationData: ( mycall: string, mywwloc: string ) => {
      dispatch(setStation( { mycall, mywwloc } ))
      dispatch(saveStation())
    }
  }
}
 ...

class StationDataModal extends React.Component<StationDataProps> {
  /* component definition ... */
}

export default connect( mapStateToProps, mapDispatchToProps ) (StationDataModal)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM