英文:
How do you navigate once your action has completed with redux-toolkit and createAsyncThunk()?
问题
已定义的操作 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 }));
// 如果 signInUser() 失败,不希望运行以下代码
navigate("/posts");
} catch (err) {
console.log(err.message);
// 如果失败,需要运行此 catch 块
}
};
根据我所知,无法在 signInUser()
操作内导航。因此,我尝试在 Login
组件的 handleSubmit()
中进行导航。但如果 signInUser()
操作引发了 catch
(由于登录失败),则我不希望在 handleSubmit()
中执行 navigate("/posts")
。我认为我需要在 handleSubmit()
中触发 catch 块,而不执行 navigate("/posts")
,或以其他方式处理它。
英文:
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?
答案1
得分: 2
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
}
}
);
英文:
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
}
}
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论