You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

  1. 安装类型依赖:
npm install @types/redux-thunk --save-dev
  1. 修改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')
);
  1. 更新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"));
    }
  };
}
  1. 组件中使用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并自动处理类型,无需手动配置:

  1. 安装Redux Toolkit:
npm install @reduxjs/toolkit react-redux
  1. 重构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')
);
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:50:24