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
相关产品推荐
相关产品推荐

