Ok so I need the message redux state to receive the message from the emailChange api call.
Im new to this so keep that in mind.
This is my function from my auth slice actions
export const emailChange = createAsyncThunk(
"auth/emailChange",
async ({ email, change }, thunkAPI) => {
const data = await AuthService.emailChange({email, change})
thunkAPI.dispatch(setMessage(data.message));
console.log(data);
return data;
})
auth slice
export const logout = createAsyncThunk("auth/logout", async () => {
await AuthService.logout();
});
const initialState = user
? { isLoggedIn: true, user }
: { isLoggedIn: false, user: null };
const authSlice = createSlice({
name: "auth",
initialState,
extraReducers: {
[register.fulfilled]: (state, action) => {
state.isLoggedIn = false;
},
[register.rejected]: (state, action) => {
state.isLoggedIn = false;
},
[login.fulfilled]: (state, action) => {
state.isLoggedIn = true;
state.user = action.payload.user;
},
[login.rejected]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
[logout.fulfilled]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
},
});
const { reducer } = authSlice;
export default reducer;
where i dispatched emailChange
const handleSubmit = (formValue) => {
setSuccessful(false);
setLoading(true);
if (change!=="email") {
dispatch(forgottenPassword(formValue))
.then((response) => {
if (response.payload.status === "PENDING"){
setSuccessful(true);
//navigate(`/emailsent/${formValue.email}/${true}`)
}
setLoading(false);
setMessage(response.payload)
})
}else if(change==="email") {
const {email} = formValue
const post = {change:true, email}
dispatch(emailChange(post))
.then((response) => {
if (response.payload.status === "PENDING"){
setSuccessful(true);
}
setLoading(false);
setMessage(response.payload)
console.log(message2) //this is the message redux state
})
}
};
api call
const emailChange = ({email, change}) => {
return api
.post("/auth/emailChange", {email, change})
.then((response) => {
return response.data;
});
};
message slice
import { createSlice } from "@reduxjs/toolkit";
const initialState = {};
const messageSlice = createSlice({
name: "message",
initialState,
reducers: {
setMessage: (state, action) => {
return { message: action.payload };
},
clearMessage: () => {
return { message: "" };
},
},
});
const { reducer, actions } = messageSlice;
export const { setMessage, clearMessage } = actions
export default reducer;
Why would this code not work?
I tried and checked many different configurations.
console logs show the correct payload is being sent to message, but the state does not update
Everything is happening correctly except the message state does not update according to console log.
I’m hoping it is something obvious in this code
This function in my auth slice actions works fine
export const register = createAsyncThunk(
"auth/register",
async ({ username, email, password }, thunkAPI) => {
try {
const response = await AuthService.register(username, email, password);
thunkAPI.dispatch(setMessage(response.data.message));
return response.data;
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
thunkAPI.dispatch(setMessage(message));
return thunkAPI.rejectWithValue();
}
}
);
2
Answers
So I managed to solve it. ultimately changing const
{message2} = useSelector((state) => state.message.message); to message2 = useSelector((state) => state.message.message);
allowed it to work.
I also put the emailchange action in its own slice and it seemed to help but not sure.
Okay so a better way to handle this is actually in the extraReducers. Heads up I personally use the "map object" notation but you can also use the builder. Here are the docs for extraReducers.
** Note it’s a good idea to define what your state will be initial state.
Also you are most likely not getting the update because you are returning. Instead you should be assigning the state in your reducers i.e. in the setMessage you should do this state.message = action.payload in redux toolkit it uses immer under the hood so you can mutate state it will handle it behind the scene.