我创建了一个后端,生成一个记录用户的json web令牌。
但是当我进入下一个屏幕时,令牌未定义。我做错了什么?
设置:
fetch('https://www.koolbusiness.com/account/mob_login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": this.state.email,
"password": this.state.password,
}),
}).then((response) => response.json())
.then((responseJson) => {
this.state.token = responseJson.token;
尝试在下一个屏幕中使用它,然后它是未定义的。
登录屏幕:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
View,
Text,Alert,
ImageBackground,
Dimensions,
LayoutAnimation,
UIManager,
KeyboardAvoidingView,
} from 'react-native';
//import { Font } from 'expo';
import { Input, Button } from 'react-native-elements'
import Icon from 'react-native-vector-icons/FontAwesome';
import SimpleIcon from 'react-native-vector-icons/SimpleLineIcons';
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
const BG_IMAGE = require('../../../assets/images/bg_screen4.jpg');
// Enable LayoutAnimation on Android
UIManager.setLayoutAnimationEnabledExperimental
&& UIManager.setLayoutAnimationEnabledExperimental(true);
const TabSelector = ({ selected }) => {
return (
<View style={styles.selectorContainer}>
<View style={selected && styles.selected}/>
</View>
);
};
TabSelector.propTypes = {
selected: PropTypes.bool.isRequired,
};
let self;
export default class LoginScreen2 extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
fontLoaded: false,
selectedCategory: 0,
isLoading: false,
isEmailValid: true,
isPasswordValid: true,
isConfirmationValid: true,
};
this.selectCategory = this.selectCategory.bind(this);
this.login = this.login.bind(this);
this.signUp = this.signUp.bind(this);
self = this;
}
async componentDidMount() {
// await Font.loadAsync({
// 'georgia': require('../../../assets/fonts/Georgia.ttf'),
// 'regular': require('../../../assets/fonts/Montserrat-Regular.ttf'),
//'light': require('../../../assets/fonts/Montserrat-Light.ttf'),
//});
this.setState({ fontLoaded: true });
}
selectCategory(selectedCategory) {
LayoutAnimation.easeInEaseOut();
this.setState({
selectedCategory,
isLoading: false,
});
}
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
login() {
const {
email,
password,
token
} = this.state;
fetch('https://www.koolbusiness.com/account/mob_login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": this.state.email,
"password": this.state.password,
}),
}).then((response) => response.json())
.then((responseJson) => {
self.setState({token:responseJson.token});
// this.state.token = responseJson.token;
this.props.state = this.state;
Alert.alert(
'Welcome',
'You are now logged in',
[
{text: responseJson.token, onPress: () => console.log('Ask me later pressed')},
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{ cancelable: false }
);
})
.catch((error) => {
console.error(error);
});
//this.setState({ isLoading: true });
// Simulate an API call
//setTimeout(() => {
// LayoutAnimation.easeInEaseOut();
// this.setState({
// isLoading: false,
// isEmailValid: this.validateEmail(email) || this.emailInput.shake(),
// isPasswordValid: password.length >= 8 || this.passwordInput.shake(),
// });
//}, 1500);
}
signUp() {
const {
email,
password,
passwordConfirmation,
} = this.state;
this.setState({ isLoading: true });
// Simulate an API call
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
isLoading: false,
isEmailValid: this.validateEmail(email) || this.emailInput.shake(),
isPasswordValid: password.length >= 8 || this.passwordInput.shake(),
isConfirmationValid: password == passwordConfirmation || this.confirmationInput.shake(),
});
}, 1500);
}
render() {
const {
selectedCategory,
isLoading,
isEmailValid,
isPasswordValid,
isConfirmationValid,
email,
password,
passwordConfirmation,
} = this.state;
const isLoginPage = selectedCategory === 0;
const isSignUpPage = selectedCategory === 1;
return (
<View style={styles.container}>
<ImageBackground
source={BG_IMAGE}
style={styles.bgImage}
>
{this.state.fontLoaded ?
<View>
<KeyboardAvoidingView contentContainerStyle={styles.loginContainer} behavior='position'>
<View style={styles.titleContainer}>
<View style={{flexDirection: 'row'}}>
<Text style={styles.titleText}>Login</Text>
</View>
<View style={{marginTop: -10, marginLeft: 10}}>
<Text style={styles.titleText}>or Sign Up</Text>
</View>
</View>
<View style={{flexDirection: 'row'}}>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(0)}
containerStyle={{flex: 1}}
titleStyle={[styles.categoryText, isLoginPage && styles.selectedCategoryText]}
title={'Login'}
/>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(1)}
containerStyle={{flex: 1}}
titleStyle={[styles.categoryText, isSignUpPage && styles.selectedCategoryText]}
title={'Sign up'}
/>
</View>
<View style={styles.rowSelector}>
<TabSelector selected={isLoginPage}/>
<TabSelector selected={isSignUpPage}/>
</View>
<View style={styles.formContainer}>
<Input
icon={
<Icon
name='envelope-o'
color='rgba(0, 0, 0, 0.38)'
size={25}
style={{backgroundColor: 'transparent'}}
/>
}
value={email}
keyboardAppearance='light'
autoFocus={false}
autoCapitalize='none'
autoCorrect={false}
keyboardType='email-address'
returnKeyType='next'
inputStyle={{marginLeft: 10}}
placeholder={'Email'}
containerStyle={{borderBottomColor: 'rgba(0, 0, 0, 0.38)'}}
ref={input => this.emailInput = input}
onSubmitEditing={() => this.passwordInput.focus()}
onChangeText={email => this.setState({ email })}
displayError={!isEmailValid}
errorMessage='Please enter a valid email address'
/>
<Input
icon={
<SimpleIcon
name='lock'
color='rgba(0, 0, 0, 0.38)'
size={25}
style={{backgroundColor: 'transparent'}}
/>
}
value={password}
keyboardAppearance='light'
autoCapitalize='none'
autoCorrect={false}
secureTextEntry={true}
returnKeyType={isSignUpPage ? 'next' : 'done'}
blurOnSubmit={true}
containerStyle={{marginTop: 16, borderBottomColor: 'rgba(0, 0, 0, 0.38)'}}
inputStyle={{marginLeft: 10}}
placeholder={'Password'}
ref={input => this.passwordInput = input}
onSubmitEditing={() => isSignUpPage ? this.confirmationInput.focus() : this.login()}
onChangeText={(password) => this.setState({password})}
displayError={!isPasswordValid}
errorMessage='Please enter at least 8 characters'
/>
{isSignUpPage &&
<Input
icon={
<SimpleIcon
name='lock'
color='rgba(0, 0, 0, 0.38)'
size={25}
style={{backgroundColor: 'transparent'}}
/>
}
value={passwordConfirmation}
secureTextEntry={true}
keyboardAppearance='light'
autoCapitalize='none'
autoCorrect={false}
keyboardType='default'
returnKeyType={'done'}
blurOnSubmit={true}
containerStyle={{marginTop: 16, borderBottomColor: 'rgba(0, 0, 0, 0.38)'}}
inputStyle={{marginLeft: 10}}
placeholder={'Confirm password'}
ref={input => this.confirmationInput = input}
onSubmitEditing={this.signUp}
onChangeText={passwordConfirmation => this.setState({ passwordConfirmation })}
displayError={!isConfirmationValid}
errorMessage='Please enter the same password'
/>}
<Button
buttonStyle={styles.loginButton}
containerStyle={{marginTop: 32, flex: 0}}
activeOpacity={0.8}
title={isLoginPage ? 'LOGIN' : 'SIGN UP'}
onPress={isLoginPage ? this.login : this.signUp}
titleStyle={styles.loginTextButton}
loading={isLoading}
disabled={isLoading}
/>
</View>
</KeyboardAvoidingView>
<View style={styles.helpContainer}>
<Button
title={'Need help ?'}
titleStyle={{color: 'white'}}
buttonStyle={{backgroundColor: 'transparent'}}
underlayColor='transparent'
onPress={() => console.log('Account created')}
/>
</View>
</View>
:
<Text>Loading...</Text>
}
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
rowSelector: {
height: 20,
flexDirection: 'row',
alignItems: 'center',
},
selectorContainer: {
flex: 1,
alignItems: 'center',
},
selected: {
position: 'absolute',
borderRadius: 50,
height: 0,
width: 0,
top: -5,
borderRightWidth: 70,
borderBottomWidth: 70,
borderColor: 'white',
backgroundColor: 'white',
},
loginContainer: {
alignItems: 'center',
justifyContent: 'center',
},
loginTextButton: {
fontSize: 16,
color: 'white',
fontWeight: 'bold',
},
loginButton: {
backgroundColor: 'rgba(232, 147, 142, 1)',
borderRadius: 10,
height: 50,
width: 200,
},
titleContainer: {
height: 150,
backgroundColor: 'transparent',
justifyContent: 'center',
},
formContainer: {
backgroundColor: 'white',
width: SCREEN_WIDTH - 30,
borderRadius: 10,
paddingTop: 32,
paddingBottom: 32,
alignItems:'center',
},
loginText: {
fontSize: 16,
fontWeight: 'bold',
color: 'white',
},
bgImage: {
flex: 1,
top: 0,
left: 0,
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
justifyContent: 'center',
alignItems: 'center',
},
categoryText: {
textAlign: 'center',
color: 'white',
fontSize: 24,
backgroundColor: 'transparent',
opacity: 0.54,
},
selectedCategoryText: {
opacity: 1,
},
titleText: {
color: 'white',
fontSize: 30,
},
helpContainer: {
height: 64,
alignItems: 'center',
justifyContent: 'center',
},
});
下一个屏幕
import React, { Component } from 'react';
import {
StyleSheet, Text, View, Image, ScrollView, Dimensions, TouchableOpacity, StatusBar, Alert
} from 'react-native';
import { Button } from 'react-native-elements'
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
const IMAGE_SIZE = SCREEN_WIDTH - 80;
class CustomButton extends Component {
constructor() {
super();
this.state = {
selected: false
};
}
componentDidMount() {
const { selected } = this.props;
this.setState({
selected
});
}
render() {
const { title } = this.props;
const { selected } = this.state;
return (
<Button
title={title}
titleStyle={{ fontSize: 15, color: 'white' }}
buttonStyle={selected ? { backgroundColor: 'rgba(213, 100, 140, 1)', borderRadius: 100, width: 127 } : { borderWidth: 1, borderColor: 'white', borderRadius: 30, width: 127, backgroundColor: 'transparent' }}
containerStyle={{ marginRight: 10 }}
onPress={() => this.setState({ selected: !selected })}
/>
);
}
}
export default class LoginScreen1 extends Component {
constructor(props) {
super(props);
this.state = {
fontLoaded: false,
};
}
async componentDidMount() {
this.setState({ fontLoaded: true });
}
render() {
Alert.alert(
'Token '+this.state.token,
'You are now logged in',
[
{text: this.state.token, onPress: () => console.log('Ask me later pressed')},
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{ cancelable: false }
);
return (
<View style={{flex: 1}}>
<StatusBar
barStyle="light-content"
/>
{ this.state.fontLoaded ?
<View style={{flex: 1, backgroundColor: 'rgba(47,44,60,1)'}}>
<View style={styles.statusBar} />
<View style={styles.navBar}>
<Text style={styles.nameHeader}>
Johanna Bloggs, 26
</Text>
</View>
<ScrollView style={{flex: 1}}>
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Image
source={{ uri: 'https://static.pexels.com/photos/428336/pexels-photo-428336.jpeg' }}
style={{ width: IMAGE_SIZE, height: IMAGE_SIZE, borderRadius: 10}}
/>
</View>
<View style={{flex: 1, flexDirection: 'row', marginTop: 20, marginHorizontal: 40, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{flex: 1, fontSize: 26, color: 'white'}}>
Johanna Bloggs {this.state.email}
</Text>
<Text style={{flex: 0.5, fontSize: 15, color: 'gray', textAlign: 'left', marginTop: 5}}>
0.8 mi
</Text>
<Text style={{flex: 1, fontSize: 26, color: 'green', textAlign: 'right'}}>
84%
</Text>
</View>
<View style={{flex: 1, marginTop: 20, width: SCREEN_WIDTH - 80, marginLeft: 40}}>
<Text style={{flex: 1, fontSize: 15, color: 'white'}}>
100% Italian, fun loving, affectionate, young lady who knows what it takes to make a relationship work.
</Text>
</View>
<View style={{flex: 1, marginTop: 30}}>
<Text style={{flex: 1, fontSize: 15, color: 'rgba(216, 121, 112, 1)', marginLeft: 40}}>
INTERESTS
</Text>
<View style={{flex: 1, width: SCREEN_WIDTH, marginTop: 20}}>
<ScrollView
style={{flex: 1}}
horizontal
showsHorizontalScrollIndicator={false}
>
<View style={{flex: 1, flexDirection: 'column', height: 170, marginLeft: 40, marginRight: 10}}>
<View style={{flex: 1, flexDirection: 'row'}}>
<CustomButton title="Philosophy" selected={true} />
<CustomButton title="Sport" />
<CustomButton title="Swimming" selected={true} />
<CustomButton title="Religion" />
</View>
<View style={{flex: 1, flexDirection: 'row' }}>
<CustomButton title="Music" />
<CustomButton title="Soccer" selected={true} />
<CustomButton title="Radiohead" selected={true} />
<CustomButton title="Micheal Jackson" />
</View>
<View style={{ flex: 1, flexDirection: 'row' }}>
<CustomButton title="Travelling" selected={true} />
<CustomButton title="Rock'n'Roll" />
<CustomButton title="Dogs" selected={true} />
<CustomButton title="France" selected={true} />
</View>
</View>
</ScrollView>
</View>
</View>
<View style={{flex: 1, marginTop: 30}}>
<Text style={{flex: 1, fontSize: 15, color: 'rgba(216, 121, 112, 1)', marginLeft: 40}}>
INFO
</Text>
<View style={{flex: 1, flexDirection: 'row', marginTop: 20, marginHorizontal: 30}}>
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{flex: 1}}>
<Text style={styles.infoTypeLabel}>Age</Text>
<Text style={styles.infoTypeLabel}>Height</Text>
<Text style={styles.infoTypeLabel}>Ethnicity</Text>
<Text style={styles.infoTypeLabel}>Sign</Text>
<Text style={styles.infoTypeLabel}>Religion</Text>
</View>
<View style={{flex: 1, marginLeft: 10}}>
<Text style={styles.infoAnswerLabel}>26</Text>
<Text style={styles.infoAnswerLabel}>5'4"</Text>
<Text style={styles.infoAnswerLabel}>White</Text>
<Text style={styles.infoAnswerLabel}>Pisces</Text>
<Text style={styles.infoAnswerLabel}>Catholic</Text>
</View>
</View>
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{flex: 1}}>
<Text style={styles.infoTypeLabel}>Body Type</Text>
<Text style={styles.infoTypeLabel}>Diet</Text>
<Text style={styles.infoTypeLabel}>Smoke</Text>
<Text style={styles.infoTypeLabel}>Drink</Text>
<Text style={styles.infoTypeLabel}>Drugs</Text>
</View>
<View style={{flex: 1, marginLeft: 10, marginRight: -20}}>
<Text style={styles.infoAnswerLabel}>Fit</Text>
<Text style={styles.infoAnswerLabel}>Vegan</Text>
<Text style={styles.infoAnswerLabel}>No</Text>
<Text style={styles.infoAnswerLabel}>No</Text>
<Text style={styles.infoAnswerLabel}>Never</Text>
</View>
</View>
</View>
</View>
</ScrollView>
</View> :
<Text>Loading...</Text>
}
</View>
);
}
}
const styles = StyleSheet.create({
statusBar: {
height: 10,
},
navBar: {
height: 60,
width: SCREEN_WIDTH,
justifyContent: 'center',
alignContent: 'center'
},
nameHeader: {
color: 'white',
fontSize: 22,
textAlign: 'center'
},
infoTypeLabel: {
fontSize: 15,
textAlign: 'right',
color: 'rgba(126,123,138,1)',
paddingBottom: 10,
},
infoAnswerLabel: {
fontSize: 15,
color: 'white',
paddingBottom: 10,
}
});
答案 0 :(得分:1)
问题是fetch是一个async
函数,而this
有时是无法访问的(至少它发生在我身上)所以,为了解决这个问题,我创建了一个名为{{1}的变量在创建类之前,我将其均衡为self
,就像我要在构造函数中编写的方式一样:
this
然后,现在您可以使用self.state之类的状态而不是this.state作为import{..}...; //your imports
let self;
class YourClass() extends Component{
constructor(){
//things you do in your constructor and at the end:
self = this;
}
}
。
我看到的问题是,如果你想把令牌放在state.token中你不能做self.state.token = responseJson.token;
,那么这样做的方法是self.state.token = responseJson.token;
或者如果你不需要使用我告诉你可以做的自我
self.setState({token:responseJson.token});
忘记我之前说过的一切
我希望它适合你。