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

React-Redux中dispatch AsyncThunkAction类型不兼容问题求助

React+Redux Toolkit中dispatch Async Thunk时的TS2345错误解决

错误描述

在React组件中dispatch携带参数的async thunk action(login)时,触发TS2345类型错误:类型为AsyncThunkAction<string, Ilogin, {}>的参数无法赋值给类型为AnyAction的参数。

错误代码片段

TS2345: Argument of type 'AsyncThunkAction<string, Ilogin, {}>' is not assignable to parameter of type 'AnyAction'.
    32 |     e.preventDefault();
    33 |     if (isEmailValid && isPasswordValid) {
  > 34 |       dispatch(login({ email: enteredEmail, password: enteredPassword }));
       |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    35 |     }
    36 |   };
    37 |

相关代码

LoginPage组件代码

import useInput from 'hooks/useInput';
import classNames from 'classnames/bind';
import { useDispatch } from 'react-redux';
import { login } from 'redux/authSlice';

import TextField from '../../components/UI/TextField';

import styles from './loginPage.module.scss';
import { FormEvent } from 'react';

const cx = classNames.bind(styles);

const LoginPage = () => {
  const dispatch = useDispatch();

  const {
    handleInputChange: handleEmailChange,
    handleBlur: handleEmailBlur,
    isTouched: isEmailTouched,
    isValid: isEmailValid,
    value: enteredEmail,
  } = useInput('email');
  const {
    handleInputChange: handlePasswordChange,
    handleBlur: handlePasswordBlur,
    isTouched: isPasswordTouched,
    isValid: isPasswordValid,
    value: enteredPassword,
  } = useInput('password');

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    if (isEmailValid && isPasswordValid) {
      dispatch(login({ email: enteredEmail, password: enteredPassword }));
    }
  };
};

authSlice代码

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { AxiosError } from 'axios';
import { Ilogin } from 'types/comminition';
import Comminition from '../apis/comminition';

interface Auth {
  token: string | undefined;
  isAuthenticated: boolean;
  status: 'success' | 'fail' | 'loading' | null;
}

const initialState: Auth = { token: undefined, isAuthenticated: false, status: null };

export const login = createAsyncThunk('authSlice/login', async (loginData: Ilogin) => {
  const response = await Comminition.login(loginData.email, loginData.password);
  return response.data.token;
});

export const authSlice = createSlice({
  name: 'authSlice',
  initialState,
  reducers: {
    logout: (state: Auth) => {
      state.isAuthenticated = false;
      state.token = undefined;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(login.pending, (state) => {
      state.status = 'loading';
    });
    builder.addCase(login.fulfilled, (state, { payload }) => {
      state.status = 'success';
      state.isAuthenticated = true;
      state.token = payload;
    });
    builder.addCase(login.rejected, (state) => {
      state.status = 'fail';
      state.isAuthenticated = false;
      state.token = undefined;
    });
  },
});

export const { logout } = authSlice.actions;
export default authSlice.reducer;

错误含义

Redux默认的useDispatch钩子返回的dispatch函数类型仅接受符合AnyAction接口的普通action,而createAsyncThunk创建的异步action返回的是AsyncThunkAction类型,该类型并不兼容AnyAction,因此TypeScript会抛出类型不匹配的错误。

解决方法

步骤1:导出自定义的AppDispatch类型

在你的Redux store配置文件(比如store.ts)中,创建store并导出对应的AppDispatch类型:

import { configureStore } from '@reduxjs/toolkit';
import authReducer from './authSlice';

export const store = configureStore({
  reducer: {
    auth: authReducer,
    // 其他reducer...
  },
});

// 导出适配当前store的dispatch类型
export type AppDispatch = typeof store.dispatch;

步骤2:在组件中使用类型化的dispatch

有两种方式可以实现:

方式一:直接指定useDispatch的类型

在LoginPage组件中导入AppDispatch,并为useDispatch指定类型:

import { useDispatch } from 'react-redux';
import { AppDispatch } from 'redux/store'; // 路径根据实际项目结构调整
import { login } from 'redux/authSlice';

// ...

const LoginPage = () => {
  // 为dispatch指定自定义的AppDispatch类型
  const dispatch = useDispatch<AppDispatch>();

  // ... 其余代码不变
};

方式二:创建自定义的useAppDispatch钩子

可以封装一个全局的自定义钩子,避免在每个组件中重复指定类型:
在hooks/useAppDispatch.ts中:

import { useDispatch } from 'react-redux';
import type { AppDispatch } from '../redux/store';

export const useAppDispatch = () => useDispatch<AppDispatch>();

然后在LoginPage组件中使用这个自定义钩子:

import { useAppDispatch } from 'hooks/useAppDispatch';
import { login } from 'redux/authSlice';

// ...

const LoginPage = () => {
  const dispatch = useAppDispatch();

  // ... 其余代码不变
};

通过以上步骤,TypeScript就能正确识别async thunk action的类型,解决类型不匹配的错误。

内容的提问来源于stack exchange,提问作者BoHyunK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:27:26