Reputation: 23
I have a problem with redux-thunk (redux-toolkit) , when I dispatch action logIn, console.log is working but this function Auth
in apiInstance.ts
file is not working
Here are my set up store and reducer
// my config's 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;
// my store
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;
// my 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") // working
Auth(action.payload, "login"); // not working
},
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),
},
});
and this is my function Auth
in apiInstance.ts
// not working
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 ( // my function
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");
}
};
I'm trying any case but it's not working, so what should I do in this case?
Upvotes: 1
Views: 80
Reputation: 499
You are not using redux toolkit correctly:
1- redux thunk is part of redux toolkit by default which means you don’t need to add it yourself, here’s my store setup: store.ts
import { configureStore } from '@reduxjs/toolkit';
//root reducer
import { reduxSlices } from './reduxSlices';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
const isDevelopment = process.env.NODE_ENV === 'development';
const store = configureStore({
reducer: reduxSlices,
devTools: isDevelopment,
middleware: (getDefaultMiddleware) => {
if (isDevelopment) {
const { logger } = require('redux-logger');
return getDefaultMiddleware().concat(logger);
}
return getDefaultMiddleware();
},
});
//type of your store if you need to use it somewhere
export type ToolkitStore = typeof store;
export type RootState = ReturnType<typeof store.getState>;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export type AppDispatch = typeof store.dispatch;
export const useAppDispatch: () => AppDispatch = useDispatch;
export default store;
2- reduxSlices.ts:
import { combineReducers } from '@reduxjs/toolkit';
// slices
/* PLOP_INJECT_IMPORT */
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';
export const slices = combineReducers({
/* PLOP_INJECT_REDUCER_SLICE */
AuthReducer,
PathVariableReducer,
codeRunner,
toastMessage,
dataDefine,
});
export const reduxSlices = (state: any, action: any) => {
/*reset redux slices except one property of a slice*/
/*if (action.type === 'user/logoutUser') {
// Preserve the state of user.featureFlags
const featureFlags = state.user.featureFlags;
// Reset the user slice to its initial state except featureFlags
const userSlice = updateObject(userInitialState, { featureFlags });
// Reset redux state
state = undefined;
state = updateObject(state, { user: userSlice });
}*/
/*reset all redux slices*/
/*if (action.type === 'user/logoutUser') {
// Reset redux state
state = undefined;
}*/
return slices(state, action);
};
3- In apiInstance.ts
you need to use createAsyncThunk
from redux toolkit:
export const loginUser = createAsyncThunk('loginUser', async () => {
await fetchCSRFToken();
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('/');
});
4- In your reducer:
const AuthReducer = createSlice({
name: 'auth',
initialState: {
isLoggingUser: false,
},
reducers: {},
extraReducers: (builder) => {
//loginUser
builder
.addCase(loginUser.pending, (state) => {
state.isLoggingUser = true;
})
.addCase(loginUser.fulfilled, (state) => {
state.isLoggingUser = false;
})
.addCase(loginUser.rejected, (state) => {
state.isLoggingUser = false;
dispatch(
TOAST_MESSAGE({
type: "error",
content: error,
duration: 5,
})
);
});
},
});
Upvotes: 0
Reputation: 131
Have you tried moving the Auth
call outside the reducer logic and dispatch it from the component where you handle login?
In your logIn
reducer, you are directly calling the Auth()
function, instead you can try to dispatch it from within a component:
// In a component or a separate action creator
dispatch(Auth(payload, "login"));
Upvotes: 0