Redux Thunk(Redux Toolkit)问题:Reducer中无法调用Auth函数
问题描述
使用Redux Toolkit结合Redux Thunk时,dispatch logIn动作后,reducer中的console.log("test")能正常执行,但apiInstance.ts中的Auth函数完全没有运行。相关代码如下:
Store配置
import { ThunkAction, thunk } from "redux-thunk"; import { Action, configureStore, getDefaultMiddleware } from "@reduxjs/toolkit"; import rootReducer from "../reducer/index.ts"; const store = configureStore({ reducer: rootReducer, middleware: [...getDefaultMiddleware(), thunk], }); export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch; export type AppThunk = ThunkAction<void, RootState, null, Action<any>>; export default store;
根Reducer
import { combineReducers } from "redux"; import AuthReducer from "./auth/index.ts"; import PathVariableReducer from "./pathVariable/index.ts"; import codeRunner from "./codeRunner/index.ts"; import toastMessage from "./toastMessage/index.ts"; import dataDefine from "./dataDefine.ts"; const rootReducer = combineReducers({ AuthReducer, PathVariableReducer, codeRunner, toastMessage, dataDefine, }); export default rootReducer;
Auth Reducer
import { createSlice } from "@reduxjs/toolkit"; import { Auth, LogOut, ResetPasswordEmail, UpdateInfor, } from "../../../service/apiInstance"; const AuthReducer = createSlice({ name: "auth", initialState: {}, reducers: { logIn: (state, action) => { console.log("test") // 正常运行 Auth(action.payload, "login"); // 无法运行 }, logOut: (state, action) => LogOut(), register: (state, action) => Auth(action.payload, "register"), forgotPassword: (state, action) => ResetPasswordEmail({ email: action.payload }), resetPassword: (state, action) => ResetPasswordEmail({ oldPassword: action.payload, newPassword: action.payload, }), updateInfor: (state, action) => UpdateInfor(action.payload), }, });
apiInstance.ts中的Auth函数
import axios from "axios"; import { TOAST_MESSAGE } from "../redux/reducer/toastMessage"; import { Dispatch } from "redux"; import { AppDispatch, AppThunk } from "../redux/store"; import { getPostSuccess } from "../redux/reducer/dataDefine"; export const Auth = (req: object, auth: string): AppThunk => async ( dispatch: AppDispatch ) => { console.log("test successful"); await fetchCSRFToken(); try { const response = await axiosInstance.post(`/${auth}`, req); localStorage.setItem("login", "true"); localStorage.setItem("name", JSON.stringify(response.data.name)); localStorage.setItem("email", JSON.stringify(response.data.email)); window.location.replace("/"); console.log(response.data); } catch (error) { dispatch(getPostSuccess); dispatch( TOAST_MESSAGE({ type: "error", content: error, duration: 5, }) ); throw new Error("Authentication failed"); } };
解决方案
核心问题
Reducer必须是纯函数,不能包含异步操作、API请求这类副作用逻辑,也不能直接调用Thunk函数。你的Auth是一个Thunk函数,它需要被dispatch才能执行,而非在Reducer里直接调用。
具体修正步骤
移除Reducer中的副作用调用
删掉AuthSlice里reducers中所有直接调用Auth、LogOut等Thunk函数的代码,只保留纯状态更新逻辑(如果需要):const AuthReducer = createSlice({ name: "auth", initialState: {}, reducers: { // 仅保留纯状态更新的同步action,比如登录成功后更新用户信息 setUser: (state, action) => { state.user = action.payload; }, }, });直接在组件中dispatch Thunk函数
在需要触发登录的组件中,直接dispatchAuth这个Thunk,而非dispatch原来的logIn同步action:import { useDispatch } from "react-redux"; import { Auth } from "./path/to/apiInstance"; const LoginComponent = () => { const dispatch = useDispatch(); const handleLogin = async (loginData) => { try { await dispatch(Auth(loginData, "login")).unwrap(); } catch (err) { console.error(err); } }; return ( // 组件内容 ); };优化Store配置(可选)
Redux Toolkit的getDefaultMiddleware已默认包含Redux Thunk,无需手动添加thunk到middleware数组,可简化配置:const store = configureStore({ reducer: rootReducer, });检查其他潜在问题
- 确认
axiosInstance是已正确配置的Axios实例,而非直接使用axios - 确认
fetchCSRFToken函数已定义且能正常执行 - 确认
TOAST_MESSAGE和getPostSuccess是可被dispatch的action creator
- 确认
内容的提问来源于stack exchange,提问作者dark123
相关产品推荐
相关产品推荐

