Возвращение рассылки с обещаниями в действии создателей реагирует на редукцию

У меня есть 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 спасибо, что вы отправите соответствующее навигационное действие, которое перенаправит вашего пользователя на нужную страницу.

Другие вопросы по тегам