我正在使用react-native
,redux
和react-navigation
构建移动应用。
我一直在思考哪个代码应该具有与屏幕转换有关的功能(例如this.props.navigation.navigate('NextScreen')
)。
例如,在我的应用中,登录过程如下。
如您所见,该应用程序在登录屏幕的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;
答案 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()