Где реализовать навигационный код для перехода к следующему экрану с избыточной и реагирующей навигацией - PullRequest
0 голосов
/ 10 ноября 2019

Я создаю мобильное приложение с react-native, redux и react-navigation.

Я думал, какой код должен иметь функцию, которая касается перехода экрана (например, this.props.navigation.navigate('NextScreen')).

Например, в моем приложении процесс входа ниже.

Процесс входа

Как видите, приложение работаетthis.props.navigation.navigate() в функции handleSignIn на экране входа в систему.

[Вопросы]

  • Иногда значение 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 голосов
/ 11 ноября 2019

По второму вопросу я перехожу по этой ссылке.

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

Наконец, я использую NavigationActions в действии вместо this.props.navigation.navigate()

0 голосов
/ 10 ноября 2019

Прежде всего, да, вы должны перейти к компоненту после того, как ваша бизнес-логика входа работает.

По поводу второго вопроса, это неправильно с использованием метода "requestSignIn". Вам необходимо отправить обратный вызов из метода requestSignIn, и он должен выглядеть примерно так:

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

Как я вижу в ваших действиях, вы уже отправляете отправку, поэтому она должна работать как в приведенном выше примере.

Почему он не работает с вашей логикой?

Это так просто, потому что не работает синхронизация, он просто переходит к следующему, если проверка, поэтому он не ожидает завершения метода requestSignIn. ,Вы даже можете использовать async / await, но диспетчер (Promise) решит это за вас:)

И последнее, я предлагаю вам использовать React Navigation Helpers для обработки всех логик навигации. Я написал это, и это решает так много грязной логики для вас:)

...