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.

I finished the project and have mine hosted on netlify. Thank you very much for this. I sent the link to someone to get one input and they told me I should have the password requirements listed on the signup page. I completely agree as most, if not all, websites have this. I have tried to add the wording in for the password requirements on Signup.js but no luck. Any advice? This tutorial is my first exposure to all of the stuff we used: js, node, react, etc.

I figured this out. I’l leave up the question and answer for others to see. I added the following Form Texts to function renderForm() on Signup.js. This was between the password and the confirm password <Form.Group>

    <Form.Group controlId="password" size="lg">
      <Form.Label>Password</Form.Label>
      <Form.Control
        type="password"
        value={fields.password}
        onChange={handleFieldChange}
      />
    </Form.Group>
    <Form.Text muted>Password must contain the following:</Form.Text>
    <Form.Text muted>8 characters</Form.Text>
    <Form.Text muted>One lowercase letter</Form.Text>
    <Form.Text muted>One uppercase letter</Form.Text>
    <Form.Text muted>One symbol</Form.Text>
    <br/>
    <Form.Group controlId="confirmPassword" size="lg">
      <Form.Label>Confirm Password</Form.Label>
      <Form.Control
        type="password"
        onChange={handleFieldChange}
        value={fields.confirmPassword}
      />
    </Form.Group>

Thank you for sharing! Appreciate it.

Hello, Ive been skipping around a bit. Does anyone know at what point we built the LoaderButton component? I dont even have a components folder in this project. I’ve been calling them containers… Thanks…

1 Like

Nevermind I fugured it out. Just had to go back through and read a little.

1 Like

I want to send the emailId from signup to dynamodb by using the /post api. Can you please describe how can i do it?