Как создать действие с аргументами, которые возвращают обещание? - PullRequest
1 голос
/ 20 января 2020

Цель: создать действие, которое возвращает обещание, принимает аргументы и использует диспетчеризацию.

лучшее, что я придумал для действия:

export const loginAction = (arg1, arg2) => {
    return (dispatch) => {
      dispatch({type: types.SOME_TYPE});
      return new Promise((resolve, reject) => {
        firebase.auth().onAuthStateChanged((user) => {
          if (user) {
            loginSuccess(dispatch, user);
            resolve(user)
          }
        }).catch(error => reject(error))
      })
    }   
}

способ, которым я хочу его реализовать:

login = () => {
  this.props.loginAction(this.state.email, this.state.password)
    .then(user => {
      if (user) {
        this.props.navigation.navigate("App")
      }
    }
}

LoginScreen:

import React from 'react';
import { loginUser, logoutUser, resetAuth, sendPwdLink } from '../actions';
import { connect } from 'react-redux';
// other imports...
const { width } = Dimensions.get('window');

class LoginScreen extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            email: '',
            password: ''
        };
    }
    goToRegister = () => {
        this.props.resetAuth();
        this.props.navigation.navigate('Register');
    };
    goToLearnMore = () => {
        this.props.navigation.navigate('LearnMore');
    };
    login = () => {
        this.props.loginUser(this.state.email, this.state.password).then((user) => {
            user ? this.props.navigation.navigate('App') : null;
        });
    };
    render () {
        return (
            <View style={styles.container}>

                <View style={{ alignItems: 'center' }}>
                    <Components.TransparentInput
                        placeholder={'Email Address...'}
                        style={{ width: width * 0.5, margin: width * 0.015, fontFamily: Fonts.QUICKSAND }}
                        placeholderColor={'white'}
                        onChangeText={(text) => {
                            this.setState({ email: text });
                        }}
                    />
                    <Components.TransparentInput
                        placeholder={'Password...'}
                        secureTextEntry={true}
                        style={{ width: width * 0.5, margin: width * 0.015, fontFamily: Fonts.QUICKSAND }}
                        placeholderColor={'white'}
                        onChangeText={(text) => {
                            this.setState({ password: text });
                        }}
                    />
                    <TouchableWithoutFeedback onPress={() => this.sendPwdLink(this.state.email)}>
                        <Text
                            style={{
                                fontSize: 14,
                                color: 'white',
                                textDecorationLine: 'underline',
                                fontFamily: Fonts.QUICKSAND
                            }}
                        >
                            Forgot password?
                        </Text>
                    </TouchableWithoutFeedback>
                </View>

                <View>
                    <Components.Button
                        type={'primary'}
                        text={'Login'}
                        onPress={this.login}
                        style={{ width: width * 0.4, margin: width * 0.015 }}
                        fontSize={18}
                    />
                    <Components.Button
                        style={{ width: width * 0.35, margin: width * 0.015 }}
                        type={'secondary'}
                        text={'Register'}
                        onPress={this.goToRegister}
                        fontSize={18}
                    />
                </View>

                <TouchableWithoutFeedback onPress={this.goToLearnMore}>
                    <Text
                        style={{
                            fontSize: 16,
                            color: 'white',
                            textDecorationLine: 'underline',
                            fontFamily: Fonts.QUICKSAND
                        }}
                    >
                        What is Slide?
                    </Text>
                </TouchableWithoutFeedback>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'space-evenly',
        alignItems: 'center',
        backgroundColor: Colors.PRIMARY_DARK
    }
});

const mapStateToProps = ({ auth }) => {
    const { authenticated, loading, error, user } = auth;
    return { authenticated, loading, error, user };
};

const mapDispatchToProps = { loginUser, logoutUser, resetAuth, sendPwdLink };

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);

Но это не работает, это приводит к ошибке: TypeError: undefined is not an object...evaluating this.props.loginAction(arg1, arg2)

РЕДАКТИРОВАТЬ: я считаю, что действия имеют доступ к dispatch через функцию mapDispatchToProps. Я могу ошибаться. Я не совсем понимаю эту часть функции действия, но она не работала без нее.

Какие изменения можно внести, чтобы это исправить?

1 Ответ

1 голос
/ 20 января 2020

[EDITED]

Прежде всего вам нужно redux-thunk .

В месте, где вы создаете магазин, вам нужно добавить это.

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(rootReducer, applyMiddleware(thunk));

Ваш loginAction правильный.

Вам просто нужно обновить mapDispatchToProps

import { bindActionCreators } from 'redux'; // dont forget to import this

const mapDispatchToProps = dispatch => 
  bindActionCreators({
    loginUser,
    logoutUser,
    resetAuth,
    sendPwdLink,
  }, dispatch);

bindActionCreators - Превращает объект в объекты, создатели действий, в объект с теми же ключами, но с каждым создателем действий, включенным в диспетчерский вызов, чтобы их можно было вызывать напрямую.

, поэтому bindActionCreators делает следующее:

const actions = { loginUser };
const bindActions = Object.keys(actions).map((action) => dispatch(action));

ссылка на proof

далее, когда вы вызываете в своем коде вашу функцию, которая является loginUser, она отправляет вашу функцию, которая относится к промежуточному программному обеспечению redux-thunk, и после redux-thunk check она запускает вашу функцию с помощью next Аргументы:

your_action_function(dispatch, getState, extraArgument);

Надеюсь, теперь вам понятно

...