Defined action signInUser
:
export const signInUser = createAsyncThunk(
"auth/loginUser",
async (user, thunkAPI) => {
const { username, password } = user;
try {
const res = await axios.post("/api/auth/login", { username, password });
thunkAPI.dispatch(loginUser(res.data));
} catch (err) {
console.log(err.message);
thunkAPI.dispatch(setErrors(err.response.data));
}
}
);
On form submission, handleSubmit()
dispatches signInUser()
action.
Component:
const Login = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
const { username, password } = formData;
try {
await dispatch(signInUser({ username, password }));
// DON'T WANT BELOW CODE TO RUN IF signInUser() FAILS (BUT IT DOES)
navigate("/posts");
} catch (err) {
console.log(err.message);
// NEED THIS CATCH TO RUN IF IT FAILS
}
};
Navigation is not possible inside of the signInUser()
action - as far as I know.
So I'm trying to navigate from within the handleSubmit()
of the Login
component. But if the signInUser()
action trips its catch
(from a failed login) then I don't want to navigate("/posts")
in the handleSubmit()
. I think I need it to trip to the catch in the handleSubmit()
and not execute navigate("/posts")
.
Or handle it some other way?
createAsyncThunk
Thunks always return a resolved Promise with either the fulfilled
or rejected
action object inside. See the Handling Thunk Results for the full details, but the basic gist is that the returned thunks have an unwrap
property that extracts the fulfilled payload
or throw the error object or payload if returned by rejectWithValue
. See Unwrapping Result Actions.
Unwrap the returned Promise.
const handleSubmit = async (e) => {
e.preventDefault();
const { username, password } = formData;
try {
await dispatch(signInUser({ username, password })).unwrap(); // <-- unwrap Promise
navigate("/posts");
} catch (err) {
console.log(err);
}
};
If the UI needs either the value or error from the Thunk then these should also be returned.
export const signInUser = createAsyncThunk(
"auth/loginUser",
async (user, thunkAPI) => {
const { username, password } = user;
try {
const { data } = await axios.post("/api/auth/login", { username, password });
thunkAPI.dispatch(loginUser(data));
return data; // <-- return POST response data
} catch (err) {
thunkAPI.dispatch(setErrors(err.response.data));
return thunkAPI.rejectWithValue(err.response.data); // <-- return error payload
}
}
);