Pt 1 here

Hi again and welcome to part two of developing with React and Create React App! In the next two parts we’re going to be doing something pretty exciting – we’ll be creating a fully working contact form that will send messages to your email address using a lambda function and Amazon SES.

Contact form example

In this part, we’ll create the front-end portion of our contact form, using CRA. Then in part 3, we’ll create the lambda and hook everything up together.

Part 1 – Lets Get the Party Started

In your terminal of choice, navigate to the folder where you want to build your project, and run the following three lines:

npx create-react-app contact-form
cd contact-form
npm start

And just like magic, a browser window will boot up and show you a pretty spinning react logo. Congrats, you now have a React app.

 

Now we can get right into coding! Lets dive into the code that has been generated to take a look at whats going on.

 

Part 2 – Navigating a React Project

Open up your new application in your favourite code editor – I recommend VS Code if you haven’t tried it. In here you can see we have a few folders. I’ll briefly go over what they’re for.

node_modules: if you’re not familiar, this folder stores all the npm packages we need to get our program running. When we install something with ‘npm install’, the files get put in here.

Public – This stores the index.html file that loads our react app.

Src – this is where the magic happens. All our react code is stored in here.

Now for the files within Src itself:

Index.js is the entry layer of our react project, and is where public/index.html file points to when it calls the app.  I’ll run over what this code is doing:

  • Line 1-2: Import React and ReactDOM so that we can use react.
  • Line 3: Import CSS styling for this page
  • Line 4: Import App.js – the other react file in this folder
  • Line 7: Render the contents of App as a component into the root.

The root is just an overarching empty component that all our React code is rendered into. ReactDOM.render takes our app component (referred to as <App />) and sticks it into the root. So imagine our react component now looks something like:

<div id=“root”>
   <App />
</div>

The rest of the code here is some optional scaffolding to use serviceworkers – which we won’t be covering in this tutorial so its safe to ignore.

Index.css and App.css – These are our styles for this project.  If you noticed in the above js file, our css styles are imported via a line of JS. This allows us to use a separate css file for each component – keeping everything modular and avoiding css spaghetti. However for this teeny example app, we’ll be putting all our styles into App.css. And, we’ll be converting it to SASS. More on that shortly.

serviceworker.js – again part of the optional service worker stuff we don’t care about for today.

app.test.js for all your unit tests. We won’t be writing any today, but its handy to have the testing framework already scaffolded out here for future use!

App.js This is where we’ll be putting all the code to render our content form! Now lets hurry up and get started.

Part 3 – Lets build!

1. Rendering a basic form

In App.js, remove everything existing in the render() component, and replace it with the following:

render() {
    return (
      <form className='App' >
        <h1>Contact me!</h1>
        <p> Drop me a message down below and i'll receive it with the power of React and Lambda!</p>
        <label>
          <span>Name: </span>
          <input type="text"/>
        </label>
        <label>
          <span>Email: </span>
          <input type="text"/>
        </label>
        <label>
          <span>Message: </span>
          <textarea rows="4" cols="50" name="comment"></textarea>
        </label>
        <button type="submit"> Submit</button>      
        </form>
    );
  }
}

Save the file, and go check out the browser tab (localhost:3000). You should see a form page! Albiet a butt-ugly one. But here you can see that rendering a component in React is as simple as writing the html you want to display inside the render method.

One interesting difference from JSX to true HMTL however, is that to give a component a class we use className instead of just class (see the <form> component in the above code). This is due to class already being a registered name in Javascript, so className is used instead.

2 – Make it Pretty!~

We want our form to look less ugly, right? Lets fix those styles.

Now, most people these days prefer using SASS or another equivalent instead of pure vanilla CSS.  This doesn’t come default with CRA, but it’s easy to add in. So now we’re going to convert our existing css files into SASS.

Run the following in your terminal, making sure you are located inside your project:

npm install node-sass


T
hen, rename App.css to App.scss. Now this file can accept Sass syntax, which makes styling a lot more convenient. 

I’ve gone ahead and written up some basic styling to get our form looking better. Delete everything in App.scss and replace with the following:

@import url(https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300);
.App {
  margin-left: 10px;
}

h1 {
  font-size: 40px;
  font-family: 'Open Sans Condensed', sans-serif;
  font-weight: bold;
}

form {
  display: flex;
  flex-direction: column;
}

input, textarea {
  height: 40px;
  line-height: 40px;
  border-color: lightgray;
  border-style: solid;
  border-width: 1px;
}

textarea {
  height: 80px;
}

button {
  background-color: pink;
  font-size: 25px;
  max-width: 150px;
  text-align: center;
  height: 50px;
  border: none;
  margin-top: 20px;
}

span {
  display: flex;
  padding-top: 20px;
}

Now look to your demo page, and you should see its looking much nicer!

3 – Make it do something

Our form looks good now, but it still doesn’t do anything. Our next job is to gather the values that the user inputs into the three fields. There are two separate listeners that we need to consider:

onChange: Whenever the value inside the textbox changes, we need to capture the new value and store it to the app’s state.

onSubmit: When the submit button is pressed, we need to do something. Eventually we will be sending the data to our lambda, but to start with lets just print out our values.

The first thing we need to do is add some state variables to store our name, email address and message. Inside the App class, create the following function:

constructor(props) {
    super(props);
    this.state = {
      name: "",
      emailaddress: "",
      message: ""
    };
    this.handleChange = this.handleChange.bind(this);
  }

The constructor() method in a React component is called before the component is mounted. So what we’re doing is ensuring that the component is created with state variables for all our form fields, and then we are binding a handleChange method (which we’ll create next). Some things to note: 

  • super(props) must be called first to make sure that ‘this.props’ is defined before we begin.
  • this.handlechange.bind(this) is needed because in Javascript, class methods aren’t bound by default. If we don’t do this, then when the method is called, it will return undefined.

Next: lets add the handleChange method. Underneath the constructor function, make a new function:

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

This allows us to update the state value of each input based on a name variable. Next we’ll need to add these name variables to our form fields and tell them to call our new method whenever a change happens.

Adjust the form JSX part of your code to include the following new variables:

<form className='App' >
<h1>Contact me!</h1>
   <p> Drop me a message down below and i'll receive it with the power of React and Lambda!</p>
   <label>
     <span>Name: </span>
     <input type="text" name="name" value={this.state.name} onChange={this.handleChange}/>
   </label>
   <label>
     <span>Email: </span>
     <input type="text" name="emailaddress" value={this.state.emailaddress} onChange={this.handleChange}/>
   </label>
   <label>
     <span>Message: </span>
     <textarea rows="4" cols="50" name="message" value={this.state.message} onChange={this.handleChange}></textarea>
   </label>
   <button type="submit"> Submit</button>      
</form>

So now, the values that are typed into the text box are saved into our state. But how can we prove that? By implementing an onSubmit method!

Add the following method under the handleChange method:

  handleSubmit(event) {
    alert(`values have been submitted!: ${this.state.name} ${this.state.emailaddress} ${this.state.message}`);
    event.preventDefault();
  }

Then bind it in the constructor like we did for handleChange:

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

And then ensure our form knows to call it when it is submitted. Modify the first line of our JSX as follows:

<form className='App' onSubmit={this.handleSubmit}>

Now go to your app, enter some fields in and press submit. SUCCESS!

So now we have a React form that captures our user’s input values and passes them to a function that runs on submit. Stay tuned for part 3, where things get really exciting – we’re going to hook it up to AWS Lambda, and pass our form values through to AWS Simple Email Service. 

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *