0

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)
  }
7
  • 3
    Arrow functions can be async too. const doSubmit = async (email_address, password) => { ... } Commented Dec 5, 2016 at 8:19
  • @CodingIntrigue could you please point me to some defintive reference to confirm this? Everything I have understood so far says "no async arrow functions". Commented Dec 5, 2016 at 8:27
  • 2
    Sure, here is the spec which calls out the syntax for use with an arrow: tc39.github.io/ecmascript-asyncawait/#prod-AsyncArrowFunction Commented Dec 5, 2016 at 8:31
  • Could you just put this into a local variable? e.g. var _this = this; Commented Dec 5, 2016 at 8:33
  • @qxz That's difficult within a class situation because you would need to store it outside of the scope of doStuff, but still allow it to have access Commented Dec 5, 2016 at 8:35

2 Answers 2

2

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")} />
      )
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

FYI async/await is not part of ES7 (ES2016). It will part of ES2017.
Thanks. I think it's time for me to switch naming to yearly in order to avoid off by one errors ;)
0

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) {
    ...
}

2 Comments

Should there be the async keyword in the above example?
@DukeDougal Oops! Kind of the main point of the answer and I omitted it :) Fixed.

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.