ReferenceError: Can't find variable: state in React Native 0.60.4

ReferenceError: Can't find variable: state in React Native 0.60.4

我正在使用 React native 0.60.4 和 react-native-router-flux 4.0.6。 我有一个工作正常的登录组件,但是当我在用户更改密码后将用户重定向到登录屏幕时,弹出上述错误并且应用程序崩溃。

我尝试在 ComponentDidMount() 中打印状态变量 - 它被打印出来了。打印了我初始化状态变量的构造函数中的所有日志。 Post 此错误弹出,应用程序崩溃。

部分错误信息:

[08:42:09] I | ReactNativeJS ▶︎ login componentDidMount

[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+)*(\.\w{2,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。不太确定这条信息是否有帮助。

嗯,您一定是直接使用了 state 而不是 this.state 才导致了这个问题。任何在构造函数中初始化而没有数据类型的东西都应该被认为是使用 this 运算符初始化的,以使其在整个 class 期间都可以使用 this.abc 进行访问。

这是因为您的 unsubscribe 函数是在 class 之外定义的,它在 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+)*(\.\w{2,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);
    }
  }
}

我只贴了修改后的函数