Search code examples
reactjsreact-nativereact-native-router-fluxreact-state

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


I am using React native 0.60.4 with react-native-router-flux 4.0.6. I have a login component which works fine but when I redirect the user to login screen after the user has changed the password, the above error pops up and the app crashes.

I tried printing the state variable in ComponentDidMount() - it gets printed. All the logs in the constructor where I am initializing the state variable are printed. Post this the error pops up and the app crashes.

Part of error message:

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

[08:42:09] E | ReactNativeJS ▶︎ ReferenceError: Can't find variable: state

I believe there is no issue in the code since its working fine whenever the app is loaded.

CODE:

    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>
            );
    }
}

I had this code running fine before I upgraded from react-native 0.56.0 to 0.60.4 and also I upgraded react-native-router-flux from ^4.0.0-beta.28 to ^4.0.6. Not very sure if this piece of information helps.


Solution

  • Well, you must have used state directly instead of this.state which is causing this issue. Anything initialised in constructor without an data type should be considered initialised using this operator to make it accessible throughout the class using this.abc.