Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Accessing this inside async/await returns undefined #6806

Closed
adeelshahid opened this issue Nov 12, 2017 · 15 comments
Closed

Bug: Accessing this inside async/await returns undefined #6806

adeelshahid opened this issue Nov 12, 2017 · 15 comments
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@adeelshahid
Copy link

same as the issue #2765

const LockIcon = styled.img.attrs({
  src: loginImg,
})``

class Login extends React.Component {
  async onLogin() {
    console.log('this', this)
    try {
      const result = await Database.login()
    } catch (err) {
      console.log('err', err)
    }
  }

  render() {
    return isEmpty(this.props.user) ? <LockIcon onClick={this.onLogin} /> : null
  }
}

Babel/Babylon Configuration (.babelrc, package.json, cli command)

  "presets": [
    [
      "env",
      {
        "modules": false,
        "loose": true,
        "targets": {
          "uglify": true
        }
      }
    ],
    "react"
  ],
  "plugins": [
    "react-hot-loader/babel",
    "transform-object-rest-spread",
    "transform-function-bind",
    "transform-class-properties",
    "transform-decorators-legacy",
    "transform-runtime"
  ]
}
{
  "your": { "config": "here" }
}

Expected Behavior

This should point to Class instance. Even using onLogin = async () => {} returns undefined.

Current Behavior

It returns undefined. Async functions should not change this context.

software version(s)
Babel 6.26.0
node 8.7.0
npm 4.6.1
Operating System Mac OSX High Sierra
@babel-bot
Copy link
Collaborator

Hey @adeelshahid! We really appreciate you taking the time to report an issue. The collaborators
on this project attempt to help as many people as possible, but we're a limited number of volunteers,
so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack
community that typically always has someone willing to help. You can sign-up here
for an invite.

@loganfsmyth
Copy link
Member

Your example is expected to fail, but the onLogin = async () => {} you mentioned should work. Are you sure it failed?

@Andarist
Copy link
Member

Andarist commented Nov 12, 2017

I've checked that this doesn't work with non-arrow functions, can be verified here

@loganfsmyth
Copy link
Member

@Andarist If it's not an arrow function then that's expected. If it's an arrow it gets turned into console.log('this', _this); though which should work fine.

@Andarist
Copy link
Member

Andarist commented Nov 12, 2017

@loganfsmyth Non-arrow functions works though too, this is not rewritten but as the function gets attached to the instance (with defineProperty) it points to the instance. I guessed that async should behave the same.

Example

@loganfsmyth
Copy link
Member

@Andarist The code sample in the issue is <LockIcon onClick={this.onLogin} /> so it'll call onLogin with no context, which means binding is a requirement for it to work for the given usecase.

@Andarist
Copy link
Member

You are right, I've misread async's output and the this there points to the instance too.

@yakovenkoroman1993
Copy link

I have the same problem. With async/await console.log(this) inside arrow function outputs undefined
image

@eldyvoon
Copy link

+1, doesn't work with react? I've this config in .babelrc

["transform-runtime", { "polyfill": false, "regenerator": true }]

@adeelshahid
Copy link
Author

adeelshahid commented Mar 14, 2018

@loganfsmyth @Andarist the process below works. If this solution looks good to you guys we can close this bug.

@eldyvoon

try the following process,

  1. Bind async function inside the constructor.
  2. Write async function as a normal function.

Example

constructor(props) {
  super(props)
  this.asyncFunc = this.asyncFunc.bind(this)
}

async function asyncFunc() {
  try {
    const result = await window.fetch(...)
  } catch (e) {}
}

@eldyvoon
Copy link

@adeelshahid why can't I use arrow function? handleChange = async (e) => {}

@adeelshahid
Copy link
Author

adeelshahid commented Mar 14, 2018

@eldyvoon babel transpilation does not correctly handle this reference when using bind and async together. Therefore I offered a workaround.

@Jessidhia
Copy link
Member

This was a bug with react-hot-loader@3; it should be fixed with react-hot-loader@4.

@yakovenkoroman1993
Copy link

yakovenkoroman1993 commented Mar 17, 2018

This issue is not reproduced in react-hot-loader 4. I checked it.

@eldyvoon
Copy link

@yakovenkoroman1993 if you don't mind, just use arrow function in jsx and do async urFunc() { console.log(this) } it will work.

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Jun 16, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Jun 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

7 participants