0

I've a React class that renders a login form, diplaying a username, password and submit button.

When the form is submitted i make an async function call (external to the class) to AWS Auth which successfully returns and writes the response to the console.

I want to use the async response in the class - how do i go about this? As i say it is writing to the console, i just need this in the class.

I've tried reading the currentsession variable directly, however, it doesn't update.

import React from 'react';
import Amplify, { Auth } from 'aws-amplify';

Amplify.configure({ // config here})

let user;
let currentsession;

export async function signIn(username, password) {
  try {
      user = await Auth.signIn(username, password);
      console.log(user);
      currentsession = await Auth.currentSession();
      console.log(currentsession);
  } catch (error) {
      console.log('error signing in', error);
  }
}

class SignIn extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: '',
      password: ''
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }
  
  handleSubmit(event) {
    signIn(this.state.username, this.state.password);
    event.preventDefault();
  }

  render() {
    return (
      <React.Fragment>
        <form onSubmit={this.handleSubmit}>
          <label>
            Name:
            <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
          </label>
          <label>
            String:
            <input type="text" name="password" value={this.state.password} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>
        <div>{ currentsession }</div>
      </React.Fragment>
    );
  }
}

export default SignIn;

UPDATE

The reply i accepted worked perfectly and answered the question. It did also inspire another answer which i've included here, removing the external function.

I realised i could make the handleSubmit function async and handle it there. Code is:

  async handleSubmit(event) {
    event.preventDefault();
    try {
      let user = await Auth.signIn(this.state.username, this.state.password);
      this.setState( { response: 'Login Success!' });
    } catch(err) {
      this.setState( { response: err.message });
    }
  }
1
  • 1
    Why is the signin function outside the class? Commented Oct 18, 2020 at 1:22

1 Answer 1

1

Do not keep variables outside of your components. Most probably, you want to keep this user and currentSession in your state. Since signIn function is async it returns a promise. Use it and update your state according to your return value.

I'm mimicking the API's here, don't mind the code. Just check the signIn function and how I return the values. You can change the logic according to your needs. Also, see the handleSubmit function to see how I update the state.

Since the code snippet doesn't support async/await (I guess) here is a working sandbox.

function userApi() {
  return new Promise((resolve) => setTimeout(() => resolve("foo"), 500));
}

function sessionApi() {
  return new Promise((resolve) => setTimeout(() => resolve("session"), 500));
}

async function signIn(username, password) {
  try {
    const user = await userApi();
    const currentSession = await sessionApi();
    return { user, currentSession };
  } catch (error) {
    console.log("error signing in", error);
    return error;
  }
}


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: "",
      password: "",
      user: null,
      currentSession: null
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  async handleSubmit(event) {
    event.preventDefault();
    const { user, currentSession } = await signIn(
      this.state.username,
      this.state.password
    );
    this.setState({ user, currentSession });
  }

  render() {
    const { user, currentSession } = this.state;
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <label>
            Name:
            <input
              type="text"
              name="username"
              value={this.state.username}
              onChange={this.handleChange}
            />
          </label>
          <label>
            String:
            <input
              type="text"
              name="password"
              value={this.state.password}
              onChange={this.handleChange}
            />
          </label>
          <input type="submit" value="Submit" />
        </form>
        <div>
          {currentSession && user && (
            <span>
              {user}-{currentSession}
            </span>
          )}
        </div>
      </div>
    );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

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.