Возвращение рассылки с обещаниями в действии создателей реагирует на редукцию
У меня есть actionCreators в моем /actions/authenticate.js
отделить логику действий, отправляемых редуксом и компонентом реакции.
Вот мой authenticate.js
который является моим actionCreators
export function login(email, password) { // Fake authentication function
return async dispatch => {
dispatch(loginRequest()); // dispatch a login request to update the state
try {
if (email.trim() === "test123@nomail.com" && password === "123456") { //If the email and password matches
const session = { token: "abc1234", email: email, username: "test123" } // Create a fake token for authentication
await AsyncStorage.setItem(DATA_SESSION, JSON.stringify(session)) // Stringinfy the session data and store it
setTimeout(() => { // Add a delay for faking a asynchronous request
dispatch(loginSuccess(session)) // Dispatch a successful sign in after 1.5 seconds
return Promise.resolve()
}, 1500)
} else { // Otherwise display an error to the user
setTimeout(() => { // Dispatch an error state
dispatch(loginFailed("Incorrect email or password"))
}, 1500)
}
} catch (err) { // When something goes wrong
console.log(err)
dispatch(loginFailed("Something went wrong"));
return Promise.reject()
}
};
} // login
Затем я импортирую это в мой someComponent.js
импортировать этот actionCreator и связать его с помощью bindActionCreators.
Примерно так ниже:
import { bindActionCreators } from "redux";
import * as authActions from "../actions/authenticate";
import { connect } from "react-redux";
Затем я подключаю это действие к своему компоненту, который является Login.js
export default connect(
state => ({ state: state.authenticate }),
dispatch => ({
actions: bindActionCreators(authActions, dispatch)
})
)(Login);
Так что я могу вызвать функцию в этом actionCreator непосредственно в Login.js
Примерно так ниже:
onPress={() => {
this.props.actions.login(this.state.email, this.state.password)
}}
Но я хочу, чтобы эта функция отправляла избыточное действие, а также возвращала обещание, если это возможно?
Что-то вроде этого:
onPress={() => {
this.props.actions.login(this.state.email, this.state.password)
.then(() => this.props.navigation.navigate('AuthScreen'))
}}
То, что я хочу, - это когда я пытаюсь войти в систему. Отправлять эти асинхронные редукционные действия, а также возвращать обещание. Если это было решено или нет, я могу перенаправить или перейти к правильному экрану.
Ценю, если кто-то может помочь. Заранее спасибо.
2 ответа
Ваш первый подход был в основном правильным. dispatch(thunkAction())
(или в вашем случае this.props.actions.login()
возвращает что угодно thunkAction()
возвращает, поэтому он возвращает Promise в случае, если это async
,
Проблема в том, к чему решает Обещание, а именно к чему вы возвращаетесь из async
функция. В твоем случае ты не ждешь setTimeout
и просто вернуться void
независимо от того, были ли правильные учетные данные или нет.
Итак, с точки зрения асинхронных функций вам нужно что-то вроде
export function login(email, password) { // Fake authentication function
return async dispatch => {
dispatch(loginRequest()); // dispatch a login request to update the state
try {
if (email.trim() === "test123@nomail.com" && password === "123456") { //If the email and password matches
const session = { token: "abc1234", email: email, username: "test123" } // Create a fake token for authentication
await AsyncStorage.setItem(DATA_SESSION, JSON.stringify(session)) // Stringinfy the session data and store it
// Add a delay for faking a asynchronous
await new Promise((resolve, reject) => setTimeout(() => resolve(), 1500));
dispatch(loginSuccess(session));
return Promise.resolve(true);
} else { // Otherwise display an error to the user
await new Promise((resolve, reject) => setTimeout(() => resolve(), 1500));
dispatch(loginFailed("Incorrect email or password"))
return Promise.resolve(false);
}
} catch (err) { // When something goes wrong
console.log(err)
dispatch(loginFailed("Something went wrong"));
return Promise.reject()
}
};
} // login
Таким образом, ваша асинхронная функция преобразуется в true
/ false
что вы можете использовать в вашем компоненте:
onPress={() => {
this.props.actions.login(this.state.email, this.state.password)
.then((login_succeeded) => this.props.navigation.navigate('AuthScreen'))
}}
Вы также можете return dispatch(loginSuccess(session));
(до тех пор, пока это возвращается, а не setTimeout
обработчик), в этом случае loginSuccess(session)
это что .then()
попадет в ваш onPress
крюк.
В случае, если вам нужно перенаправить пользователя на другую страницу в зависимости от login
результат, вы должны использовать Redux Router, то в вашем login
спасибо, что вы отправите соответствующее навигационное действие, которое перенаправит вашего пользователя на нужную страницу.