Evanss
Evanss

Reputation: 23563

Async function in React doesn't have access to this

I'm using React with Apollo Client. When a user logs in I need to refetch the USER query so that I can decide where to redirect them based on what fields are present in their profile.

My code hangs at this line:

await this.props.USER.refetch();

I think this is because making the function async changes the context of this.

async login() {

  const result = await this.props.LoginMutation({
    variables: {
      email: this.state.email,
      password: this.state.password,
    },
  });

  const token = await result.data.authenticateUser.token;

  await this._saveUserData(token);

  // This is where the code hangs 
  await this.props.USER.refetch();


  // If no user profile pic has been set then redirect to the account page
  if (!this.props.USER.user.profilePic) {
    this.setState({
      redirect: '/account',
    });
  }

  // If no location is set redirect to the homepage
  if (!this.props.USER.user.location) {
    this.setState({
      redirect: '/',
    });
  }

  if (this.props.USER.user.location) {
    this.setState({
      redirect: `/${this.props.USER.user.location.machineName}`,
    });
  }

  this.setState({
    redirect: `/`,
  });
}

React dev tools shows me that this.props.USER.refetch() does exist:

enter image description here

Upvotes: 1

Views: 2036

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281646

Its not because of async that the function achieves a different context, but because functions in ES6 class need to be be bound explicitly. Make use of arrow function like

login = async () => {

  const result = await this.props.LoginMutation({
    variables: {
      email: this.state.email,
      password: this.state.password,
    },
  });

  const token = await result.data.authenticateUser.token;

  await this._saveUserData(token);

  // This is where the code hangs 
  await this.props.USER.refetch();


  // If no user profile pic has been set then redirect to the account page
  if (!this.props.USER.user.profilePic) {
    this.setState({
      redirect: '/account',
    });
  }

  // If no location is set redirect to the homepage
  if (!this.props.USER.user.location) {
    this.setState({
      redirect: '/',
    });
  }

  if (this.props.USER.user.location) {
    this.setState({
      redirect: `/${this.props.USER.user.location.machineName}`,
    });
  }

  this.setState({
    redirect: `/`,
  });
}

Upvotes: 1

Related Questions