Определенное действие 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.info(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.info(err.message);
// NEED THIS CATCH TO RUN IF IT FAILS
}
};
Навигация внутри действия signInUser()
невозможна, насколько мне известно.
Итак, я пытаюсь перемещаться изнутри handleSubmit()
компонента Login
. Но если действие signInUser()
срабатывает catch
(из-за неудачного входа в систему), то я не хочу navigate("/posts")
в handleSubmit()
. Я думаю, мне нужно, чтобы он срабатывал в улове в handleSubmit()
, а не казнил navigate("/posts")
.
Или как-то по-другому с этим справиться?
createAsyncThunk
Преобразователи всегда возвращают разрешенное обещание с объектом действия fulfilled
или rejected
внутри. См. Обработка результатов преобразования для получения полной информации, но основная суть заключается в том, что возвращаемые переходы имеют свойство unwrap
, которое извлекает выполненное payload
или выдает объект ошибки или полезную нагрузку, если возвращается rejectWithValue
. См. Действия с результатами распаковки.
Разверните возвращенное обещание.
const handleSubmit = async (e) => {
e.preventDefault();
const { username, password } = formData;
try {
await dispatch(signInUser({ username, password })).unwrap(); // <-- unwrap Promise
navigate("/posts");
} catch (err) {
console.info(err);
}
};
Если пользовательскому интерфейсу требуется либо значение, либо ошибка от 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
}
}
);
@Р.Дж. Как правило, вы не должны смешивать async/await
|try/catch
с цепочками обещаний. Как правило, вы должны использовать один или другой. Одно не обязательно рекомендуется или лучше другого.
Последний. Лучше ли отправлять в действии - w/thunkAPI.dispatch()? Или лучше вернуть данные из преобразователь и диспетчера в handleSubmit() компонента?
@Р.Дж. Зависит от того, где вы хотите/нужны данные. Если это нужно только пользовательскому интерфейсу, то вернуть его можно. Если данные необходимо сохранить, то отправка действия для их сохранения в состоянии также допустима. Написание thunk для выполнения обоих действий — это нормально, и оно охватывает оба варианта использования. Это зависит от варианта использования.
Работает хорошо. И код выглядит хорошо для вас? Try/catch(s), async/await(s) – или рекомендуются промисы?