DEV Community

Cover image for Working with Controlled Forms In React
Anthony Mendoza
Anthony Mendoza

Posted on

Working with Controlled Forms In React

Working with forms in React can be a bit daunting at first especially if it needs to make its way to your Back-end. Today I'm gonna try to make the process easier, we are going to be building out a form for a new user account.

1. Functional Component Or Class Component?

To start we need to know if we are going to be keeping state or lifecycle methods in this component. For this particular component, we are gonna need state to keep track of the user input. Making this component a class component like so.

import React from 'react';

class SignUp extends React.Component {
    state = {
        email: '',
        password: '',
        passwordConfirmation: '',
        firstName: '',
        lastName: ''

    }
    }
Enter fullscreen mode Exit fullscreen mode
2. Our Form

In our Return, we need to write our form in JSX. To keep our code DRY, we are going to add a few more things to our form to save us time down the road.

  <h3 className='signup-header'>Sign up!</h3>
   <form onSubmit={this.handleSubmit}>
    <input
         name='email'
     value={this.state.email}                        
         onChange={this.handleChange}                        
         type='text'                         
         placeholder='Email'
       /> 
       <br></br>

     <input
     name='firstName'
         value={this.state.firstName}                        
         onChange={this.handleChange}                        
         type='text'
     placeholder='first name...'
      />
      <br></br>

    <input
     name='lastName'
     value={this.state.lastName}
         onChange={this.handleChange}
     type='text'
     placeholder='last name...'
     />
     <br></br>

    <input                       
         name='password'
         value={this.state.password}
     onChange={this.handleChange}
     type='password'
     placeholder='password'
    />

    <input
    name='passwordConfirmation'
    value={this.state.passwordConfirmation}
    onChange={this.handleChange}
    type='password'
    placeholder=' confirm password'
    />

    <button type='submit' class='btn btn-primary'>
    Sign Up
    </button>
</form>
Enter fullscreen mode Exit fullscreen mode

So whats going on with our form? first, by us setting our inputs with an attribute of 'name' we can play around with our event listener as I will show you in a bit. Secondly, our value attribute is what will make sure that our input and state are in sync leaving state as a single source of truth.
Next up our 'onChange' is our event listener, in this case, we need to keep track of anything the user types in and we are tying this to our handle change function that I will show next. The next key part of our form is our button to submit. Make sure that it is set to type=' submit', so our submit handler can keep track of it.

3. Our Functions

First, we need to keep track of our input and this is where adding that name attribute to our form will save us a lot of typing. When adding the name attribute to a form make sure 100% that it is exactly how it's written in our state if not nothing will get updated. I'm going to show you both ways without a name and with a name.

Without name attribute on form
handleEmail(event) {
    this.setState({email: event.target.value});
  }

handleFirstName(event) {
    this.setState({firstName: event.target.value});
  }

handleLastName(event) {
    this.setState({lastName: event.target.value});
  }

handlePassword(event) {
    this.setState({password: event.target.value});
  }

handlePasswordConfirmation(event) {
    this.setState({passwordConfirmation: event.target.value});
  }
Enter fullscreen mode Exit fullscreen mode
With a name attribute on form
handleChange = e => {
        console.log(e.target.value);
        this.setState({ [e.target.name]: e.target.value });
    };
Enter fullscreen mode Exit fullscreen mode

By doing this we are setting our state to the name that was passed in and the value would be whatever user input is typed in.

4. Handling our submits

Lastly, we need to handle where our forms will go. For this, I will send a 'POST' request, for this work we will need to add a submission to the very top of our form
<form onSubmit={this.handleSubmit}> and our handle submit function will look like so

handleSubmit = e => {
let { email, password, passwordConfirmation, firstName, lastName} = this.state

e.preventDefault();

if (password === passwordConfirmation) {
fetch('http://localhost:3000/signup', {
  method: 'POST',
   headers: {
    'Content-Type': 'application/json',
     Accept: 'application/json',
    },
body: JSON.stringify({
           email, 
           password, 
           passwordConfirmation, 
           firstName, 
           lastName
    }),
    })
    .then(resp => resp.json())
    .then(data => {
         this.setState({
        email: '',
        password: '',
        passwordConfirmation: '',
        firstName: '',
        lastName: ''
         //with the data we can update our front-end
         //redirect here
      });
     })
        } else{
           alert("Passwords don't match!");
          }
    };
Enter fullscreen mode Exit fullscreen mode

So to begin, using some es6 magic we can deconstruct our states to just their names and if those names match what is on your database in our body we can just write it one time and should work as long as the names match. Next, we need to make sure we don't prompt a refresh of the page and we can do so by adding a .preventDefault the next part is not needed to submit a form but I wanted to check that password and password confirmation are the same if not give an alert that passwords don't match. lastly, we make our fetch and reset the form by setting the state back to blank.

Hopefully I was able to be of some help when researching forms for react. :)

Top comments (0)