In my app I am calling logout api(post) and AsyncStorage.clear();
then my login screen come but some how unable to store state.
I am also unable to click on login screen button and other component.
This is my slice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import loginService from "../../services/userService";
export const logout = createAsyncThunk("logout", async (action) => {
const response = await loginService.logout(action);
return response.data;
});
const userSlice = createSlice({
name: 'userDetails',
initialState: {
loading: false,
error: null,
message: null,
success: false,
details: null,
secret: null,
authorizeSecret: null,
isPwdReseted: false,
deviceInfomation: {},
},
extraReducers: (builder) => {
builder.addCase(logout.pending, (state, action) => {
state.loading = true;
state.success = false;
});
builder.addCase(logout.fulfilled, async (state, action) => {
state.loading = false;
state.success = action.payload.Success;
state.message = action.payload.Message;
if (action.payload.Success && action.payload.StatusCode === 200) {
await AsyncStorage.clear();
console.log('Storage Clear');
}
});
builder.addCase(logout.rejected, (state, action) => {
state.loading = false;
state.success = false;
state.error = action.payload
});
}
});
this is console log
Possible Unhandled Promise Rejection (id: 2):
Error: Invariant failed: A state mutation was detected between dispatches, in the path 'userDetails.loading'. This may cause incorrect behavior. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)
Error: Invariant failed: A state mutation was detected between dispatches, in the path 'userDetails.loading'. This may cause incorrect behavior. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)
I know some how I didn't get initial state for my login screen, but why I don't know.
The logout.fulfilled
reducer case function is declared async
and so implicitly returns a Promise object instead of the next state.
builder.addCase(
logout.fulfilled,
async (state, action) => { // <-- implicit Promise returned
state.loading = false;
state.success = action.payload.Success;
state.message = action.payload.Message;
if (action.payload.Success && action.payload.StatusCode === 200) {
await AsyncStorage.clear();
console.log('Storage Clear');
}
}
);
Redux reducer functions are to be pure, synchronous functions.
Move the asynchronous "side-effect" of clearing the storage into the asynchronous action. Update the logout.fulfilled
reducer function to be synchronous and only update the state.
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import loginService from '../../services/userService';
export const logout = createAsyncThunk(
"logout",
async (action) => {
const response = await loginService.logout(action);
if (response.Success && response.StatusCode === 200) {
await AsyncStorage.clear();
console.log('Storage Clear');
}
return response.data;
}
);
const userSlice = createSlice({
name: "userDetails",
initialState: {
...
},
extraReducers: (builder) => {
builder
.addCase(logout.pending, (state, action) => {
state.loading = true;
state.success = false;
});
.addCase(logout.fulfilled, (state, action) => {
state.loading = false;
state.success = action.payload.Success;
state.message = action.payload.Message;
});
.addCase(logout.rejected, (state, action) => {
state.loading = false;
state.success = false;
state.error = action.payload
});
},
});