Я создаю мобильное приложение с 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;