【发布时间】:2018-12-18 05:33:24
【问题描述】:
我目前正在使用 react native 开发应用程序,现在我的问题是登录后我无法导航到主屏幕。下面是我的代码。
这是 App.js(已编辑)
import React from 'react';
import { Loading } from './components/common/';
import TabNavigator from './screens/TabNavigator';
import AuthNavigator from './screens/AuthNavigator';
import MainNavigator from './screens/MainNavigator';
import deviceStorage from './services/deviceStorage.js';
import { View, StyleSheet } from 'react-native';
export default class App extends React.Component {
constructor() {
super();
this.state = {
token: '',
loading: true
}
this.newJWT = this.newJWT.bind(this);
this.deleteJWT = deviceStorage.deleteJWT.bind(this);
this.loadJWT = deviceStorage.loadJWT.bind(this);
this.loadJWT();
}
state = {
isLoadingComplete: false,
};
newJWT(token){
this.setState({
token: token
});
}
render() {
if (this.state.loading) {
return (
<Loading size={'large'} />
);
} else if (!this.state.token) {
return (
<View style={styles.container}>
<AuthNavigator screenProps = {{setToken:this.newJWT}} />
</View>
);
} else if (this.state.token) {
return (
<View style={styles.container}>
<MainNavigator screenProps = {{token: this.state.token,
deleteJWT:this.deleteJWT,}} />
</View>
);
}
}
}
这是 Login.js (EDITED-v2)
import React, { Component, Fragment } from 'react';
import { Text, View, StyleSheet, ImageBackground, KeyboardAvoidingView,
TouchableOpacity, TextInput, Alert } from 'react-native';
import axios from 'axios';
import deviceStorage from '../services/deviceStorage';
class Login extends Component {
constructor(props) {
super(props)
this.state = {
username: '',
password: '',
error: '',
loading: false
};
this.loginUser = this.loginUser.bind(this);
this.onLoginFail = this.onLoginFail.bind(this);
}
loginUser() {
const { username, password, password_confirmation } = this.state;
this.setState({ error: '', loading: true });
// NOTE Post to HTTPS only in production
axios.post("http://192.168.1.201:8000/api/login",{
username: username,
password: password
})
.then((response) => {
console.log('response',response)
deviceStorage.saveKey("token", response.data.token);
console.log(response.data.token);
this.props.newJWT(response.data.token);
})
.catch((error) => {
const status = error.response.status
if (status === 401) {
this.setState({ error: 'username or password not recognised.' });
}
this.onLoginFail();
//console.log(error);
//this.onLoginFail();
});
}
onLoginFail() {
this.setState({
error: 'Login Failed',
loading: false
});
}
render() {
// other codes here
}
const styles = StyleSheet.create({
// other codes here
});
export { Login };
这是 TabNavigator.js(已添加)
import React from 'react';
import { Text } from 'react-native';
import { createMaterialTopTabNavigator } from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import Profile from '../screens/Profile';
const TabNavigator = createMaterialTopTabNavigator(
{
Profile: {
screen: props => <Profile {...props.screenProps} />,
navigationOptions: {
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-person' : 'ios-person'} //TODO change to focused
icon
size={30}
style={{ color: tintColor }}
/>
),
}
},
},
{ initialRouteName: 'Profile',
tabBarPosition: 'top',
swipeEnabled: false,
animationEnabled: true,
lazy: true,
tabBarOptions: {
showLabel: false,
showIcon: true,
activeTintColor: 'orange',
inactiveTintColor: 'orange',
style: {
backgroundColor: '#555',
},
indicatorStyle: {
color: '#orange'
}
}
}
);
const screenTitles = {
Profile: { title: 'Profiler' },
Home: { title: 'Home' },
};
TabNavigator.navigationOptions = ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
const headerTitle = screenTitles[routeName].title;
const tabBarVisible = false;
return {
headerTitle,
tabBarVisible
};
};
export default TabNavigator;
这是我的 AuthLoadingScreen.js
import React from 'react';
import { View } from 'react-native';
import { Login } from '../screens/Login';
class AuthLoadingScreen extends React.Component {
constructor(props){
super(props);
this.state = {
showLogin: true
};
this.whichForm = this.whichForm.bind(this);
this.authSwitch = this.authSwitch.bind(this);
}
authSwitch() {
this.setState({
showLogin: !this.state.showLogin
});
}
whichForm() {
if(this.state.showLogin){
return(
<Login newJWT={this.props.newJWT} authSwitch={this.authSwitch} />
);
} else {
}
}
render() {
return(
<View style={styles.container}>
{this.whichForm()}
</View>
);
}
}
export default AuthLoadingScreen;
const styles = {
// style codes here
};
最后,这是我的 Profile.js
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Alert, Platform } from
'react-native';
import { Button, Loading } from '../components/common/';
import axios from 'axios';
export default class Profile extends Component {
constructor(props){
super(props);
this.state = {
loading: true,
email: '',
name: '',
error: ''
}
}
componentDidMount(){
this.onLocationPressed();
const headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.props.token
};
axios({
method: 'GET',
url: 'http://192.168.1.201:8000/api/user',
headers: headers,
}).then((response) => {
console.log('response',response)
console.log('response2',this.props.token)
this.setState({
email: response.data.user.email,
name: response.data.user.name,
loading: false
});
}).catch((error) => {
console.log(error);
this.setState({
error: 'Error retrieving data',
loading: false
});
});
}
render() {
const { container, emailText, errorText } = styles;
const { loading, email, name, error } = this.state;
if (loading){
return(
<View style={container}>
<Loading size={'large'} />
</View>
)
} else {
return(
<View style={container}>
<View>
<Text style={emailText}>Your email: {email}</Text>
<Text style={emailText}>Your name: {name}</Text>
</View>
<Button onPress={this.props.deleteJWT}>
Log Out
</Button>
</View>
);
}
}
}
const styles = {
// style codes here
};
我已经修复了之前无法启动应用的问题。现在我可以看到登录屏幕,但是当我按下登录时,有一个黄色框表示有问题。我已经包含了下面的屏幕截图。
最后我添加了 deviceStorage.js
deviceStorage.js
import { AsyncStorage } from 'react-native';
const deviceStorage = {
async saveKey(key, valueToSave) {
try {
await AsyncStorage.setItem(key, valueToSave);
} catch (error) {
console.log('AsyncStorage Error: ' + error.message);
}
},
async loadJWT() {
try {
const value = await AsyncStorage.getItem('token');
if (value !== null) {
this.setState({
token: value,
loading: false
});
} else {
this.setState({
loading: false
});
}
} catch (error) {
console.log('AsyncStorage Error: ' + error.message);
}
},
async deleteJWT() {
try{
await AsyncStorage.removeItem('token')
.then(
() => {
this.setState({
token: ''
})
}
);
} catch (error) {
console.log('AsyncStorage Error: ' + error.message);
}
}
};
export default deviceStorage;
【问题讨论】:
-
您忘记导出登录组件。你有
class Login extends Component {但你没有最后一行export { Login }就像我的代码一样 -
我还建议您使用不同于 ScreenComponent 名称的路由名称。例如
Login路由转到LoginScreen。它会为您省去一些麻烦。 -
@Augusto 我已经在页面的最底部包含了 export { Login }。请问您使用与 ScreenComponent 不同的路由名称是什么意思?顺便说一句,我可以看到登录页面,但是当我按下登录按钮时,我无法登录,并且出现黄色框错误,我不知道这是什么意思,我已经包含了屏幕截图。
-
@Augusto 我可以在登录后将令牌传递给导航器并获取用户详细信息。但是现在我有一个小问题,当我按下登录时,应用程序显示黄色框错误,但在我重新启动应用程序后,它跳转到主屏幕,即选项卡导航器。那么我该如何解决这个错误呢?
-
别在意路线名称。这并不重要。关于错误,您的 error.response 对象未定义。通过在登录 API 调用的 catch 部分记录 console.log(error) 检查您的 API 响应。
标签: react-native react-navigation