簡體   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