Duke Dougal
Duke Dougal

Reputation: 26326

How can I get "this" into scope in a ReactJS ES2015 async function?

Below is a method that is within an ES2015 class.

It cannot be an arrow function because it is an async function.

But since it is not an arrow function, "this" is not in scope so I cannot do things like setstate.

Can someone please suggest how I can get this into scope? thanks!

  async doSubmit(email_address, password) {
    this.setState({isSubmitting: true, error: null})
    try {
      let data = await this.props.app.server.doSignIn(email_address, password)
    } catch (jqXHR) {
      let errorType = (jqXHR.status >= 400 && jqXHR.status < 500) ? 'application' : 'system'
      let errorMessage = (errorType === 'application') ? jqXHR.responseJSON.description : jqXHR.error
      this.setState({error: errorMessage, isSubmitting: false})

    }
    // following a signin event make sure the user image changes
    this.props.app.reloadProfileImages()
    try {
      await this.props.app.initializeClouds()
    } catch (err) {
      xog('err', err)
      this.setState({error: errorMessage, isSubmitting: false})
    }
    this.postSignIn(data)
  }

Upvotes: 0

Views: 180

Answers (2)

CodingIntrigue
CodingIntrigue

Reputation: 78525

You've got a few options. Firstly, arrow functions can be async, you just need to attach it to a property of the class:

constructor() {
    this.doSubmit = async (email_address, password) => {

    };
}

Here's an example of that working in the Babel REPL.

If you want to keep the class declaration the way it is, you can use bind within the constructor to ensure the this reference is always bound to the class instance:

constructor() {
    this.doSubmit = this.doSubmit.bind(this);
}

async doSubmit(email_address, password) {
    ...
}

Upvotes: 0

Przemysław Zalewski
Przemysław Zalewski

Reputation: 3986

As you already use async/await ES7 feature you can also use property initializer syntax to automatically have this in scope. It's in the stage-2 Babel preset.

class Example extends React.Component {
    doSubmit = async (email_address, password) => {
        this.setState({isSubmitting: true, error: null})
        try {
          let data = await this.props.app.server.doSignIn(email_address, password)
        } catch (jqXHR) {
          let errorType = (jqXHR.status >= 400 && jqXHR.status < 500) ? 'application' : 'system'
          let errorMessage = (errorType === 'application') ? jqXHR.responseJSON.description : jqXHR.error
          this.setState({error: errorMessage, isSubmitting: false})
        }
        ...
    }

    render() {
      return (
        <button onClick={this.doSubmit("[email protected]", "password")} />
      )
    }
}

Upvotes: 2

Related Questions