ReferenceError:找不到变量:React Native 0.60.4 中的状态
Posted
技术标签:
【中文标题】ReferenceError:找不到变量:React Native 0.60.4 中的状态【英文标题】:ReferenceError: Can't find variable: state in React Native 0.60.4 【发布时间】:2019-12-24 11:35:04 【问题描述】:我正在使用 React native 0.60.4 和 react-native-router-flux 4.0.6。 我有一个可以正常工作的登录组件,但是当我在用户更改密码后将用户重定向到登录屏幕时,会弹出上述错误并且应用程序崩溃。
我尝试在ComponentDidMount()
中打印状态变量 - 它被打印出来。打印了我正在初始化状态变量的构造函数中的所有日志。
发布此错误会弹出并且应用程序崩溃。
部分错误信息:
[08:42:09] 我 | ReactNativeJS ▶︎ 登录组件DidMount
[08:42:09] E | ReactNativeJS ▶︎ ReferenceError: Can't find variable: state
我相信代码中没有问题,因为每当加载应用程序时它都可以正常工作。
代码:
import * as React from 'react';
// import React, Component from "react";
import
StyleSheet,
Text,
TouchableOpacity,
Toastandroid,
AppState,
Dimensions,
View,
ImageBackground,
Image,
DeviceEventEmitter,
LayoutAnimation,
UIManager,
Platform,
Keyboard
// AsyncStorage
// NetInfo
from "react-native";
import AsyncStorage from '@react-native-community/async-storage';
import NetInfo from '@react-native-community/netinfo';
import Actions from 'react-native-router-flux';
import Bars from 'react-native-loader';
import Nointernet from './NoInternet';
import axios from 'axios';
import TextField from './lib/TextField';
import PermissionsAndroid from 'react-native';
import firebase from 'react-native-firebase';
let deviceWidth = Dimensions.get('window').width;
let elementWidth = 0.8*deviceWidth;
let screenHeigth = Dimensions.get('window').height;
const unsubscribe=NetInfo.addEventListener((change)=> this.handleConnectivityChange );
class LoginScreen extends React.Component
constructor(props)
console.log("Props done");
super(props);
console.log("State issue");
this.state =
appState: AppState.currentState,
hidePwd:true,
pntoken: '',
username: '',
passwd: '',
text: '',
checkinternet:false,
nointernet:false,
isLoading: false ,
visibleHeight: Dimensions.get('window').height ,
logo_height:100,
logo_width:100,
pwd_backup:''
;
console.log("State initialized");
this.handleConnectivityChange = this.handleConnectivityChange.bind(this);
this._handleAppStateChange = this._handleAppStateChange.bind(this);
this.requestLocationPermission = this.requestLocationPermission.bind(this);
if (Platform.OS === 'android')
UIManager.setLayoutAnimationEnabledExperimental(true);
async getfcmtooken()
let pn_token = await firebase.messaging().getToken();
if(pn_token)
console.log("PNTOKEN")
// if(this.state!=undefined)
// this.setState( pntoken: pn_token);
console.log("have TOKN");
// if(this.state!=undefined)
// console.log(this.state.pntoken);
this.updateToken(pn_token);
else
console.log("Loggged in. PN_TOKEN")
this.tokenRefreshListener = firebase.messaging().onTokenRefresh((pn_token) =>
console.log('response getfcmtooken');
if (pn_token)
console.log("got token")
// if(this.state!=undefined)
// this.setState( pntoken: pn_token)
this.updateToken(pn_token);
// if(this.state!=undefined)
// console.log(this.state.pntoken);
);
console.log('getfcmtooken')
updateToken(token)
console.log('App updateToken');
AsyncStorage.getItem('org_id').then((orgId) =>
if(orgId != null)
console.log('orgId');
console.log(orgId);
let org_id = JSON.parse(orgId);
console.log('org_id');
console.log(org_id);
AsyncStorage.getItem('email').then((useremail) =>
let email = JSON.parse(useremail);
if(email)
console.log('email');
AsyncStorage.getItem('token').then((tokenvalue) =>
if(tokenvalue!=null)
console.log('user_id');
console.log(tokenvalue);
let tokenV = JSON.parse(tokenvalue);
console.log("PN TOKEN");
console.log(token);
axios(
method: 'PUT',
url: this.props.apiurl+'/pushnotification/updatetoken',
data: JSON.stringify(
email: email,
pntoken: token,
),
timeout: 30000,
headers:
Accept: 'application/json',
'Content-Type': 'application/json',
authorization:tokenV
).then((response)=>
console.log("RESPONSE")
console.log(response);
)
.catch(error=>
console.log("ERROR")
console.log(error);
)
// return fetch(this.props.apiurl+'/pushnotification/updatetoken',
// method: 'PUT',
// headers:
// Accept: 'application/json',
// 'Content-Type': 'application/json',
// ,
// body: JSON.stringify(
// email: email,
// pntoken: token,
// ),
// )
// .then((response) =>
// console.log('222222222222');
// console.log(response);
// response.json()
// )
// .then((responseJson) =>
// console.log('kkkkkkkkkkkkkkk');
// console.log(responseJson);
// )
// .catch((error) =>
// console.log('error');
// console.log(error);
// );
);
);
);
async requestCameraPermission()
try
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
'title': 'Camera Permission',
'message': 'needs access to your camera '
)
if (granted)
console.log("You can use the camera")
this.requestLocationPermission()
else
console.log("Camera permission denied")
catch (err)
console.warn(err)
async requestLocationPermission()
try
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
'title': 'Camera Permission',
'message': 'needs access to your location '
)
if (granted)
console.log("You can use the location")
else
console.log("location permission denied")
catch (err)
console.warn(err)
componentDidMount()
console.log(this.state);
console.log("login componentDidMount");
this.getfcmtooken();
NetInfo.fetch().then((connectionInfo) =>
if(connectionInfo.type != 'none')
console.log("NETINFO");
this.setState( checkinternet : false ,nointernet : false );
this.requestCameraPermission();
else
this.setState( checkinternet : false ,nointernet : true );
)
.catch((response)=>
console.log(response);
);
AppState.addEventListener('change', this._handleAppStateChange);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this))
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this))
_handleAppStateChange = (nextAppState) =>
console.log("CHECKING STATE");
if (this.state.appState.match(/active/) && nextAppState === 'background')
console.log('App has come to the background!')
console.log("CHECKED STATE")
this.setState(appState: nextAppState);
console.log("NEW STATE SET");
NetInfo.fetch()
.then((connectionInfo) =>
if(connectionInfo.type != 'none')
this.setState( nointernet : false );
else
this.setState( nointernet : true );
)
.catch((response)=>
console.log(response);
);
handleConnectivityChange()
NetInfo.fetch().then((connectionInfo) =>
if(connectionInfo.type != 'none')
console.log("INTERNET CHECK 1")
this.setState( nointernet : false );
console.log("INTERNET CHECKED 1")
else
console.log("INTERNET CHECK 2")
this.setState( nointernet : true );
console.log("INTERNET CHECKED 2")
)
.catch((response)=>
console.log(response);
);
componentWillUnmount()
AppState.removeEventListener('change', this._handleAppStateChange);
NetInfo.removeEventListener('connectionChange', this.handleConnectivityChange );
// unsubscribe();
this.keyboardDidShowListener.remove()
this.keyboardDidHideListener.remove()
keyboardDidShow (e)
console.log('Key Event');
console.log(Dimensions.get('window').height+' - '+e.endCoordinates.height);
let newSize = Dimensions.get('window').height - e.endCoordinates.height
console.log('new size')
console.log(newSize);
console.log('wind_width')
console.log(Dimensions.get('window').width);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
this.setState(
visibleHeight: newSize,
logo_width:50,
logo_height:50
)
keyboardDidHide (e)
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
this.setState(
visibleHeight: Dimensions.get('window').height,
logo_height:100,
logo_width:100
)
managePwd()
this.setState(
hidePwd:!this.state.hidePwd
)
login()
if(this.state.username != '')
let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w2,3)+$/ ;
if(reg.test(this.state.username) === true)
if(this.state.passwd != '')
return fetch(this.props.apiurl+'/mobilelogin',
method: 'POST',
headers:
Accept: 'application/json',
'Content-Type': 'application/json',
,
body: JSON.stringify(
email: this.state.username,
password: this.state.passwd,
pntoken: this.state.pntoken,
),
)
.then((response) => response.json())
.then((responseJson) =>
if(responseJson.statusCode == 200)
this.setState(
isLoading: false,
text: responseJson.result.authenticateUser.userRole,
dataSource: responseJson
, function()
try
console.log('TOKEN');
console.log(JSON.stringify(responseJson.result.authenticateUser.token));
AsyncStorage.setItem('token', JSON.stringify(responseJson.result.authenticateUser.token));
AsyncStorage.setItem('email', JSON.stringify(responseJson.result.authenticateUser.email));
AsyncStorage.setItem('userRole', JSON.stringify(responseJson.result.authenticateUser.userRole));
AsyncStorage.setItem('org_id', JSON.stringify(responseJson.result.authenticateUser.orgId));
AsyncStorage.setItem('user_id', JSON.stringify(responseJson.result.authenticateUser.userId));
this.getfcmtooken();
AppState.removeEventListener('change', this._handleAppStateChange);
unsubscribe();
// NetInfo.removeEventListener('connectionChange', this.handleConnectivityChange );
Actions.landing();
catch (error)
console.log(error)
);
else
ToastAndroid.show(responseJson.authenticateUser.statusMessage,ToastAndroid.LONG);
)
.catch((error) =>
console.log('error');
console.log(error);
);
else
ToastAndroid.show('Password is mandatory',ToastAndroid.LONG);
else
ToastAndroid.show('Email is not in correct form',ToastAndroid.LONG);
else
ToastAndroid.show('Email is mandatory',ToastAndroid.LONG);
render()
console.log("RENDERING ...");
if(this.state.checkinternet)
console.log("LOADING...CONNECTION ")
return <View style=flex:1, backgroundColor: '#fff'>
<View style=height:screenHeigth-60, justifyContent:'center',alignItems:'center'>
<Bars size=25 color="#eb5828" />
</View>
</View>;
if (this.state.nointernet)
return <View>
<Nointernet/>
</View>;
return (
<View style=[styles.container,height: this.state.visibleHeight]>
<ImageBackground
style=[styles.topLogo1,height: this.state.visibleHeight]
source=require('../assets/Background.png')
>
<View style=styles.upperContainer>
<View style=styles.signintextContainer>
<Image style=height:this.state.logo_height,width:this.state.logo_width source=require('../assets/WhiteLogo.png')/>
<Text style=styles.appname>Smart Timer</Text>
</View>
</View>
<View style=styles.formContainer>
<View style=[width:elementWidth,styles.elementcontainer]>
<TextField
label='E-mail ID'
highlightColor='#fff'
onChangeText=(username) => this.setState(username)
value=this.state.username
keyboardType='email-address'
autoCapitalize='none'
textColor='#fff'
wrapperStyle= height: 60
labelStyle= color: '#fff', fontFamily: 'Lato-Regular'
/>
</View>
<View style=[width:elementWidth,styles.elementcontainer]>
<View style=styles.textBoxBtnHolder>
<TextField
label='Password'
highlightColor='#fff'
secureTextEntry=this.state.hidePwd
onChangeText=(passwd) => this.setState(passwd)
value=this.state.passwd
autoCapitalize='none'
textColor='#fff'
wrapperStyle= height: 60
labelStyle= color: '#fff', fontFamily: 'Lato-Regular'
/>
<TouchableOpacity style=styles.visibilityBtn onPress=this.managePwd.bind(this) >
<Image style= marginRight:10, height: 25,width: 25 source=this.state.hidePwd?require('../assets/private.png'):require('../assets/view.png')/>
</TouchableOpacity>
</View>
</View>
<TouchableOpacity style=[ width:elementWidth,styles.buttonRaised ] onPress=this.login.bind(this) >
<Text style=[ styles.buttonText ]>Login</Text>
</TouchableOpacity>
<View style=styles.signupTextContainer>
<View>
<TouchableOpacity onPress=() => Actions.forgotpassword(apiurl:this.props.apiurl) >
<Text style=[ styles.signupText ]>Forgot Password | </Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress=() => Actions.register(apiurl:this.props.apiurl) >
<Text style=[ styles.signupTextblack ]> Sign Up</Text>
</TouchableOpacity>
</View>
</View>
</View>
</ImageBackground>
</View>
);
在我从 react-native 0.56.0 升级到 0.60.4 之前,我的这段代码运行良好,我还将 react-native-router-flux 从 ^4.0.0-beta.28 升级到 ^4.0.6。不太确定这条信息是否有帮助。
【问题讨论】:
它可以和 this.state 一起使用,你能分享你的代码吗? 用代码编辑问题 这是因为你有unsubscribe
函数在类之外编写
@warl0ck 当我第一次加载它时应该给我一个错误......但它工作正常......我仍在尝试你的建议。希望它有效...
我已经提到了这些更改,看看是否可行,当你打电话给unsubscribe
时,它不会删除订阅,因为你必须删除EventListener 并进行必要的更改。
【参考方案1】:
好吧,您一定是直接使用了 state 而不是导致此问题的 this.state。任何在没有数据类型的构造函数中初始化的东西都应该被认为是使用this
操作符初始化的,以便使用this.abc
在整个类中访问它。
【讨论】:
我也认为这是一个问题并检查了这个....但是找不到任何这样的实例....我只使用 this.state 访问了状态....我想知道这是否与 react-native-router-flux 或导航代码有关...【参考方案2】:这是因为您的 unsubscribe
函数是在类之外定义的,该函数在 login
函数中被调用,此外,当您在登录时调用 unsubscribe
时,它应该只是 NetInfo.removeEventListener(...)
和
NetInfo.addEventListener((change) => this.handleConnectivityChange );
应该改为
this.unsubscribe = NetInfo.addEventListener('connectionChange', this.handleConnectivityChange);
所以最后应该是这样的:
let deviceWidth = Dimensions.get('window').width;
let elementWidth = 0.8 * deviceWidth;
let screenHeigth = Dimensions.get('window').height;
class LoginScreen extends React.Component
constructor(props)
console.log("Props done");
super(props);
console.log("State issue");
this.state =
appState: AppState.currentState,
hidePwd: true,
pntoken: '',
username: '',
passwd: '',
text: '',
checkinternet: false,
nointernet: false,
isLoading: false,
visibleHeight: Dimensions.get('window').height,
logo_height: 100,
logo_width: 100,
pwd_backup: ''
;
console.log("State initialized");
this.handleConnectivityChange = this.handleConnectivityChange.bind(this);
this.unsubscribe = NetInfo.addEventListener('connectionChange', this.handleConnectivityChange);
this._handleAppStateChange = this._handleAppStateChange.bind(this);
this.requestLocationPermission = this.requestLocationPermission.bind(this);
if (Platform.OS === 'android')
UIManager.setLayoutAnimationEnabledExperimental(true);
componentDidMount()
console.log(this.state);
console.log("login componentDidMount");
this.getfcmtooken();
NetInfo.fetch().then((connectionInfo) =>
if (connectionInfo.type != 'none')
console.log("NETINFO");
this.setState( checkinternet: false, nointernet: false );
this.requestCameraPermission();
else
this.setState( checkinternet: false, nointernet: true );
)
.catch((response) =>
console.log(response);
);
AppState.addEventListener('change', this._handleAppStateChange);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this))
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this))
login()
if (this.state.username != '')
let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w2,3)+$/;
if (reg.test(this.state.username) === true)
if (this.state.passwd != '')
return fetch(this.props.apiurl + '/mobilelogin',
method: 'POST',
headers:
Accept: 'application/json',
'Content-Type': 'application/json',
,
body: JSON.stringify(
email: this.state.username,
password: this.state.passwd,
pntoken: this.state.pntoken,
),
)
.then((response) => response.json())
.then((responseJson) =>
if (responseJson.statusCode == 200)
this.setState(
isLoading: false,
text: responseJson.result.authenticateUser.userRole,
dataSource: responseJson
, function ()
try
console.log('TOKEN');
console.log(JSON.stringify(responseJson.result.authenticateUser.token));
AsyncStorage.setItem('token', JSON.stringify(responseJson.result.authenticateUser.token));
AsyncStorage.setItem('email', JSON.stringify(responseJson.result.authenticateUser.email));
AsyncStorage.setItem('userRole', JSON.stringify(responseJson.result.authenticateUser.userRole));
AsyncStorage.setItem('org_id', JSON.stringify(responseJson.result.authenticateUser.orgId));
AsyncStorage.setItem('user_id', JSON.stringify(responseJson.result.authenticateUser.userId));
this.getfcmtooken();
AppState.removeEventListener('change', this._handleAppStateChange);
// this.unsubscribe();
NetInfo.removeEventListener('connectionChange', this.handleConnectivityChange );
Actions.landing();
catch (error)
console.log(error)
);
else
ToastAndroid.show(responseJson.authenticateUser.statusMessage, ToastAndroid.LONG);
)
.catch((error) =>
console.log('error');
console.log(error);
);
else
ToastAndroid.show('Password is mandatory', ToastAndroid.LONG);
else
ToastAndroid.show('Email is not in correct form', ToastAndroid.LONG);
else
ToastAndroid.show('Email is mandatory', ToastAndroid.LONG);
我只粘贴了更改后的功能。
【讨论】:
还是同样的问题吗?即使没有打电话给this.unsubscribe()
?.你能从 chrome 调试器分享崩溃日志吗?而不是来自 adb 日志?并在使用箭头函数时从 _handleAppStateChange
函数中删除 bind
。
刚刚注意到从 _handleAppStateChange
函数中删除绑定,因为您正在使用箭头函数,它会自动为您绑定它。
在做出您建议的更改后再次尝试...仍然是同样的问题以上是关于ReferenceError:找不到变量:React Native 0.60.4 中的状态的主要内容,如果未能解决你的问题,请参考以下文章