React18+Redux Toolkit使用Redux-Thunk派发事件类型不匹配报错求助
React 18 + Redux Thunk 类型错误解决方案
问题描述
使用Redux-Thunk时触发TypeScript类型错误:
Argument of type '(dispatch: any) => Promise<void>' is not assignable to parameter of type 'AnyAction'
错误出现在Action的派发环节,核心原因是TypeScript无法识别Thunk Action的类型——默认dispatch仅接受标准Action对象,不支持返回函数的Thunk。
相关代码
Store 配置文件
import { Provider } from 'react-redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import { legacy_createStore as createStore , applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; const store = createStore(rootReducer,composeWithDevTools(applyMiddleware(thunk))); ReactDOM.render(<Provider store={store}> <App/> </Provider>,document.getElementById('root'));
PlayerDetails.Action.tsx
import * as ACTION_TYPES from './action-types'; import * as CONSTANTS from '../utils/Constants' const axios = require('axios'); const rax = require('retry-axios'); export const playerDetails_request = (data: any)=>{ return { type: ACTION_TYPES.GET_PLAYER_DETAILS_REQUEST, payload : data } } export const playerDetails_success = (obj: any)=>{ return { type: ACTION_TYPES.GET_PLAYER_DETAILS_SUCCESS, payload : obj } } export const playerDetails_failure = (err: any)=>{ return { type: ACTION_TYPES.GET_PLAYER_DETAILS_FAILURE, payload : err } } export default function getPlayersDetails(data:any){ return async function (dispatch:any) { dispatch(playerDetails_request(data)); try{ axios.defaults.withCredentials = true; const interceptorId = rax.attach(); const response = await axios ({ url:CONSTANTS.PLAYER_DETAILS, method:'GET', params: {page: '0', per_page: '25'}, headers: CONSTANTS.header, }); if(response !==null && response.status === 200){ dispatch(playerDetails_success(response)); }else{ dispatch(playerDetails_failure(response)); } }catch(error){ console.log("ERROR"); dispatch(playerDetails_failure("ERROR")) } } }
action-types.tsx
export const GET_PLAYER_DETAILS_REQUEST = "GET_PLAYER_DETAILS_REQUEST" export const GET_PLAYER_DETAILS_SUCCESS = "GET_PLAYER_DETAILS_SUCCESS" export const GET_PLAYER_DETAILS_FAILURE = "GET_PLAYER_DETAILS_FAILURE"
解决步骤
方案1:手动配置Thunk类型(传统Redux)
- 安装类型依赖:
npm install @types/redux-thunk --save-dev
- 修改Store配置,添加类型定义:
import { Provider } from 'react-redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import { legacy_createStore as createStore, applyMiddleware, AnyAction } from 'redux'; import thunk, { ThunkDispatch } from 'redux-thunk'; import rootReducer from './reducers'; // 替换为你的rootReducer路径 // 定义全局状态类型和Dispatch类型 type RootState = ReturnType<typeof rootReducer>; export type AppDispatch = ThunkDispatch<RootState, any, AnyAction>; const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk))); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
- 更新Action文件的类型注解:
import * as ACTION_TYPES from './action-types'; import * as CONSTANTS from '../utils/Constants'; import axios from 'axios'; // 替换require为ES模块导入 import rax from 'retry-axios'; import { AnyAction } from 'redux'; import type { AppDispatch, RootState } from '../store'; // 导入定义好的类型 export const playerDetails_request = (data: any) => ({ type: ACTION_TYPES.GET_PLAYER_DETAILS_REQUEST, payload: data, }); export const playerDetails_success = (obj: any) => ({ type: ACTION_TYPES.GET_PLAYER_DETAILS_SUCCESS, payload: obj, }); export const playerDetails_failure = (err: any) => ({ type: ACTION_TYPES.GET_PLAYER_DETAILS_FAILURE, payload: err, }); export default function getPlayersDetails(data: any) { // 使用AppDispatch代替any return async (dispatch: AppDispatch) => { dispatch(playerDetails_request(data)); try { axios.defaults.withCredentials = true; const interceptorId = rax.attach(); const response = await axios({ url: CONSTANTS.PLAYER_DETAILS, method: 'GET', params: { page: '0', per_page: '25' }, headers: CONSTANTS.header, }); if (response !== null && response.status === 200) { dispatch(playerDetails_success(response)); } else { dispatch(playerDetails_failure(response)); } } catch (error) { console.log("ERROR"); dispatch(playerDetails_failure("ERROR")); } }; }
- 组件中使用dispatch时指定类型:
import { useDispatch } from 'react-redux'; import getPlayersDetails from './PlayerDetails.Action'; import type { AppDispatch } from './store'; const dispatch = useDispatch<AppDispatch>(); // 此时派发Thunk Action不会再触发类型错误 dispatch(getPlayersDetails(yourData));
方案2:改用Redux Toolkit(推荐)
Redux Toolkit内置Thunk并自动处理类型,无需手动配置:
- 安装Redux Toolkit:
npm install @reduxjs/toolkit react-redux
- 重构Store配置:
import { configureStore } from '@reduxjs/toolkit'; import rootReducer from './reducers'; const store = configureStore({ reducer: rootReducer, devTools: process.env.NODE_ENV !== 'production', // 自动启用DevTools }); // 导出全局类型 export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
- Action文件可以直接使用RTK的
createAsyncThunk简化编写:
import { createAsyncThunk } from '@reduxjs/toolkit'; import * as CONSTANTS from '../utils/Constants'; import axios from 'axios'; import rax from 'retry-axios'; export const getPlayersDetails = createAsyncThunk( 'player/getDetails', async (data: any, { rejectWithValue }) => { try { axios.defaults.withCredentials = true; rax.attach(); const response = await axios({ url: CONSTANTS.PLAYER_DETAILS, method: 'GET', params: { page: '0', per_page: '25' }, headers: CONSTANTS.header, }); if (response.status === 200) { return response.data; } return rejectWithValue(response); } catch (error) { return rejectWithValue("ERROR"); } } );
RTK会自动生成请求中、成功、失败的Action类型,同时完全兼容TypeScript类型检查。
内容的提问来源于stack exchange,提问作者Aditya Karthik
相关产品推荐
相关产品推荐

