1

I'm currently using React Native 0.39.2 w/ newest TypeScript and when I run my componentDidMount() method and setState I get an error around this.setState is not a function.

I tried binding with this.setState({isLoggedIn: true}).bind(this)

though since I'm using a boolean as the type it won't let me without giving a type error and even setting to any type still gets same error.

here's my code

First with my interface for State

import React, {
 Component
} from 'react';
import { AppRegistry, View, StyleSheet, Text } from 'react-native';
import { Actions } from 'react-native-router-flux';

import Firestack from 'react-native-firestack';

const firestack = new Firestack();

interface Props {

}

interface State {
  isLoggedIn?: boolean;
}


export default class MainList extends Component<Props, State> {

   state = {
     isLoggedIn: false,
   };

   constructor(props: any) {

      super(props);
      console.log("Is anyone logged in?: " + this.isLoggedIn);

   }

   isLoggedIn = this.state.isLoggedIn;

   componentDidMount() {

      if (!this.isLoggedIn) {

          Actions.welcome();

      }

      firestack.auth.listenForAuth(function(evt: any) {
      // evt is the authentication event
      // it contains an `error` key for carrying the
      // error message in case of an error
      // and a `user` key upon successful authentication

        if (!evt.authenticated) {
        // There was an error or there is no user
        //console.error(evt.error);

        this.setState({isLoggedIn: false});
        console.log("The state of isLoggedIn is: " +       this.isLoggedIn);

        } else {
        // evt.user contains the user details
        console.log('User details', evt.user);

        this.setState({isLoggedIn: true});
        console.log("The state of isLoggedIn is: " + this.isLoggedIn);

        }


    }); 

}

render() {

    return (
        <View style={styles.View}>

            <Text style={styles.textLabel}>The main view</Text>

        </View>
     )

   }

 }

 const styles = StyleSheet.create({

 View: {
    padding: 20
 },
 textLabel: {
    fontSize: 20,
    marginBottom: 10,
    height: 20
 },
 textInput: {
    height: 20,
    fontSize: 15,
    marginBottom: 20
  }

});

AppRegistry.registerComponent('MainList', ()=> MainList);

Is there anything I'm missing here?

2
  • 1
    post your whole file. how are you declaring your class? Commented Dec 24, 2016 at 2:40
  • looks like there is a great deal you are missing Commented Dec 24, 2016 at 3:10

1 Answer 1

3

The issue is because in the callback function for listenForAuth, this is no longer referring to the MainList object.

Try switching to arrow function expression which solve the this binding issue:

firestack.auth.listenForAuth((evt: any) => {
  ...
});

Here is a good read if you want to know more about arrow function.

Sign up to request clarification or add additional context in comments.

4 Comments

thank you so much :-) i should of realized this but I forgot to mention I am a little new, but this helped so much especially the help reference at the end!
You are welcome! There are a few other solutions (e.g. bind(this) or var that = this;), but I find it a lot more easier using arrow function (which was introduced in ES6).
would I do the var that = this; outside the class definition if i were to do that i'm gathering?
You can define var that = this; inside componentDidMount() function, then you can use that.setState() in the callback function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.