In this code snippet I want to know why async
and await
not working.
This code in my component I am sure that is no errors:
const { success, loading, error } = useSelector(
(state) => state.loginReducer
);
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: async (values) => {
await dispatch(login(values));
console.log(success);
},
});
This is the slice:
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const initialState = {
token: localStorage.getItem("token"),
loading: false,
error: null,
success: false,
};
export const login = createAsyncThunk("login/login", async (values) => {
const { data } = await axios.post(
"https://note-sigma-black.vercel.app/api/v1/users/signIn",
values
);
return data;
});
const loginSlice = createSlice({
name: "login",
initialState,
extraReducers: function (builder) {
builder.addCase(login.pending, (state) => {
state.loading = true;
});
builder.addCase(login.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
builder.addCase(login.fulfilled, (state, action) => {
state.loading = false;
state.token = action.payload.token;
state.success = true;
localStorage.setItem("token", action.payload.token);
});
},
});
export default loginSlice.reducer;
I expect that while I dispatch a promise function async
and await
should work.
2
Answers
Here, your
console.log(success)
won’t show the updated value immediately after the dispatch because React batches state updates for the next render. To track the updated state, you should use theuseEffect
hook withsuccess
in the dependency array. This ensures thatuseEffect
runs after the component has re-rendered with the new state.While
dispatch
itself is synchronous, the state changes (and thus the component re-renders) happen asynchronously, meaning you can’t make the code "pause" to reflect the updated state immediately after dispatch. However,useEffect
ensures you can track the newsuccess
value after the render has occurred.What makes you think the asynchronous code it not working? The code appears syntactically correct to me, I see no overt issues. If you are referring to the
console.log(success);
line after awaiting the dispatched action, this won’t work as you are likely expecting because the submit handler call has a Javascript Closure over the selectedsuccess
from the time it is called. In other words, the callback can’t possibly see any updated selected state values from outside the closure scope. If you really wanted to check the success value then access the current state value viastore.getState
.Basic example for demonstration, though you should avoid this generally.
But if all you really want to know, or verify, is that the login succeeds or fails from within the submit handler, the login logic could be improved to handle Promise rejections and errors better. See Handling Thunk Results and Handling Thunk Errors for complete details.
Update the
login
Thunk to catch and handle any fetching errors/issues, and return a rejection value (typically the error or error message).Update the submit handler to properly unwrap and handle the Thunk action result.
If the
login
Thunk is successful, you’ll continue in thetry
branch, otherwise if there are any thrown exceptions or thelogin
Thunk rejects, thecatch
block is executed and you know the login was unsuccessful.