Create the Signup Form

From @jayair on Mon Apr 10 2017 01:05:04 GMT+0000 (UTC)

Link to chapter - http://serverless-stack.com/chapters/create-the-signup-form.html

Copied from original issue: https://github.com/AnomalyInnovations/serverless-stack-com/issues/45

First of all, absolutely delighted by what you’ve put together here. This is like Wikipedia, or Khan Academy, but for software development (on the cloud). Anyone who reads this has a blank canvas to build ever they want. The value of the blank canvas however, is exceptionally underrated.

I had a problem where users would interrupt the sign-in flow, and thus no longer be able to confirm their account. I needed to re-use the confirmation view and logic from the Login page. I decided to build a ConfirmationCode component that could be used for this purpose.

The ConfirmationCode component:

import React, { Component } from "react";
import { Auth } from "aws-amplify";
import {
  HelpBlock,
  FormGroup,
  FormControl,
  ControlLabel,
} from "react-bootstrap";
import LoaderButton from "../components/LoaderButton";

export default class ConfirmationCode extends Component {
  constructor(props) {
    super(props);

    this.state = {
        isLoading: false,
        confirmationCode: ""
    };
  }

  handleChange = event => {
    this.setState({
      [event.target.id]: event.target.value
    });
  }

  validateConfirmationForm() {
    return this.state.confirmationCode.length > 0;
  }

  handleConfirmationSubmit = async event => {
    event.preventDefault();

    this.setState({ isLoading: true });

    try {
      await Auth.confirmSignUp(this.props.email, this.state.confirmationCode);
      await Auth.signIn(this.props.email, this.props.password);

      this.props.confirmSuccess();
    } catch (e) {
        // TODO: Improve
      alert(e.message);
      this.setState({ isLoading: false });
    }
  }

  render() {
    console.log(this.props);
    return (
        <form onSubmit={this.handleConfirmationSubmit} id="registration">
          <FormGroup controlId="confirmationCode" bsSize="large">
            <ControlLabel>Confirmation Code</ControlLabel>
            <FormControl
              autoFocus
              type="tel"
              value={this.state.confirmationCode}
              onChange={this.handleChange}
            />
            <HelpBlock>Please check your email for the code.</HelpBlock>
          </FormGroup>
          <LoaderButton
            block
            bsSize="large"
            disabled={!this.validateConfirmationForm()}
            type="submit"
            isLoading={this.state.isLoading}
            text="Verify"
            loadingText="Verifying…"
          />
        </form>
    );
  }
}

Exactly as it exists in Signup, only we changed the password and email references to use props instead of this. It needs to be this way because we are now passing in those variables when we call the component. The only other alteration is the call to confirmSuccess(), also passed in as a property. This allows the calling function an ability to pass a callback.

On the Login page, first we have to add the component.

<ConfirmationCode email={this.state.email} password={this.state.password} confirmSuccess={this.confirmSuccess} />

We’ll also need to modify our catch (e) block to check for the right exception that is thrown from signIn. Let’s also add a state variable showConfirmation to control the rendering of the component.

if (e.code === "UserNotConfirmedException") {
        this.setState({ showConfirmation: true});
      }

Our confirmSuccess callback simply executes the existing logic, before we made it a component.

confirmSuccess = async event => {
  this.props.userHasAuthenticated(true);
  this.props.history.push("/");      
}

Lastly, you can incorporate it in your render method like:

render() {
    return (
      <div className="Login">
      {this.state.showConfirmation
          ? this.renderConfirmation()
          : this.renderLogin()}
        
      </div>
    );
  }

Works great!

1 Like

Thank you for the kind words! I’m glad you see the value in what’ve put together!

Also, thank you for sharing the code you used to fix the issue. It ends up being very helpful for anybody searching for ways to build on top of what we have.