定义动作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));
}
}
);
在表单提交时,handleSubmit()
调度signInUser()
的动作。
组件:
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
}
};
导航是不可能的signInUser()
行动内部-据我所知。
所以我试图从Login
组件的handleSubmit()
内导航。但是,如果signInUser()
的行动绊倒了它的catch
(从一个失败的登录),那么我不想在handleSubmit()
的navigate("/posts")
。我想我需要它在handleSubmit()
中捕获,而不是执行navigate("/posts")
。
还是用其他方法处理?
createAsyncThunk
Thunksalways返回一个包含fulfilled
或rejected
操作对象的解析Promise。详细信息请参见Handling Thunk Results,但基本要点是返回的Thunk有一个unwrap
属性,用于提取已完成的payload
,或者如果由rejectWithValue
返回则抛出错误对象或有效负载。参见展开结果操作。
打开返回的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);
}
};
如果UI需要Thunk的值或错误,那么它们也应该返回。
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
}
}
);