在哪里实现导航代码以通过redux和react-navigation移动下一个屏幕

时间:2019-11-10 08:25:22

标签: react-native redux react-navigation

我正在使用react-nativereduxreact-navigation构建移动应用。

我一直在思考哪个代码应该具有与屏幕转换有关的功能(例如this.props.navigation.navigate('NextScreen'))。

例如,在我的应用中,登录过程如下。

Sign In Process

如您所见,该应用程序在登录屏幕的handleSignIn函数中运行this.props.navigation.navigate()

[问题]

  • 有时状态中的uid值为空白,如果用户成功登录,则应填写该值,但有时不能填写。我该如何解决?
  • this.props.navigator.navigator()是在屏幕组件中定义的函数中执行的,对吗?

有我的代码。

  • 登录屏幕
import React, { Component } from 'react';
import { ActivityIndicator, Keyboard, KeyboardAvoidingView, StyleSheet } from 'react-native';
import { connect } from 'react-redux';

: 

class SignIn extends Component {

  async handleSignIn() {
    const { navigation, requestSignIn } = this.props;
    const { uid, email, password, error } = this.props.auth;
    Keyboard.dismiss();

    requestSignIn(email, password);

    // sometimes this uid is blank
    if (uid) {
      alert('success');

      // this function should be executed here?
      navigation.navigate('Match', { uid: uid });
    } else {
      alert(error);
    }
  }

  render() {
    const { navigation, changeText } = this.props;
    const { email, password, loading } = this.props.auth;

    return (
     :
            <Button gradient onPress={() => this.handleSignIn()}>
              { loading ?
                <ActivityIndicator size='small' color='white' /> :
                <Text bold white center>Sign In</Text>
              }
            </Button>
     :
    )
  }
}

const mapStateToProps = state => {
  return {
    auth: state.auth
  }
};
const mapDispatchToProps = dispatch => {
  return {
    requestSignIn: (email, password) => dispatch(auth.requestSignIn(email, password)),
  }
};

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

:
  • 动作
:
export const REQUEST_SIGN_IN_SUCCESS = 'REQUEST_SIGN_IN_SUCCESS';
export const REQUEST_SIGN_IN_FAILURE = 'REQUEST_SIGN_IN_FAILURE';

export function requestSignIn(email, password) {
  return async function (dispatch) {
    // change loading status
    dispatch(startedRequest());

    if (email && password) {
      await firebase.auth().signInWithEmailAndPassword(email, password)
        .then(response => {
          if (response) {
            // save email and password in local secure storage.
            SecureStorage.setItem('email', email);
            SecureStorage.setItem('password', password);

            dispatch(requestSignInSuccess(response.user.uid))
          } else {
            return Promise.resolve(new Error(response));
          }
        })
        .catch(error => {
          switch (error.code) {
            case 'auth/user-not-found':
              dispatch(requestSignInFailure('user not found'));
              break;
            case 'auth/invalid-email':
              dispatch(requestSignInFailure('invalid email'));
              break;
            default:
              dispatch(requestSignInFailure('something went wrong'))
          }
        })

    } else {
      dispatch(requestSignInFailure('error message from else statement'))
    }
  }
}

export function requestSignInSuccess(uid) {
  return {
    type: REQUEST_SIGN_IN_SUCCESS,
    payload: {
      uid: uid
    }
  }
}

export function requestSignInFailure(errorMessage) {
  return {
    type: REQUEST_SIGN_IN_FAILURE,
    payload: {
      errorMessage: errorMessage
    }
  }
}
  • 减速器
import * as ActionType from '../actions/auth';

const initialState = {
  uid: '',
  email: '',
  password: '',
  isLoading: false,
  error: {
    message: ''
  }
};

const auth = (state=initialState, action) => {
  const { type, payload } = action;

  switch (type) {
    case ActionType.STARTED_REQUEST:
      return Object.assign({}, state, {
        isLoading: true
      });
    case ActionType.CHANGE_TEXT:
      return Object.assign({}, state, {
        [payload.key]: payload.value
      });
    case ActionType.REQUEST_SIGN_IN_SUCCESS:
      return Object.assign({}, state, {
        uid: payload.uid,
        isLoading: false,
      });
    case ActionType.REQUEST_SIGN_IN_FAILURE:
      return Object.assign({}, state, {
        isLoading: false,
        error: {
          message: payload.errorMessage,
        },
      });
    default:
      return { ...state };
  }
};

export default auth;

2 个答案:

答案 0 :(得分:0)

首先,是的,您应该在登录业务逻辑工作后导航到组件。

关于第二个问题,使用“ requestSignIn”方法是错误的。您需要从requestSignIn方法发送一个回调,它应该像这样:

requestSignIn((result) => {
  if(result){
    const { uid } = result;
    uid && navigate("Match", {uid});
  }
})

正如我在您的操作中看到的那样,您已经发送了一个调度,因此它应该像上面的示例一样工作。

为什么它不符合您的逻辑?

它是如此简单,因为它不工作同步,如果进行检查,它只会转到下一个,因此它不会等到requestSignIn方法完成。您甚至可以使用async / await,但是dispatch(Promise)可以为您解决:)

最后一件事,我建议您使用React Navigation Helpers处理所有导航逻辑。我已经写了它,它为您解决了很多肮脏的逻辑:)

答案 1 :(得分:0)

关于第二个问题,我点击了此链接。

https://github.com/daose/react-native-template/issues/1

最后,我在操作中使用NavigationActions而不是this.props.navigation.navigate()