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) =&gt; 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 中的状态的主要内容,如果未能解决你的问题,请参考以下文章

ReferenceError:找不到变量

ReferenceError:找不到变量:$

ReferenceError:找不到变量:堆栈

ReferenceError:找不到变量:__gCrWeb

ReferenceError:找不到变量:React -- bundle android

QML 和 C++ 属性 - ReferenceError:找不到变量