React Forms

I. React Forms

Forms in React is quite different from Vanilla JavaScript.

Instead of waiting at the end to gather all of the information, we constantly keep track of all information in state.

Therefore, we can have the most updated version of what user is typing into the form.

We accomplish this by doing the following two steps:

  • Whenever the input value is changed, call an event handler to update the component state to the new input value
  • Re render the the React Element with its value attribute set to the updated state input value

II. Functional components

For functional components, we use React Hook’s useState to control input.

Step 1

To start, let’s define a functional component and create a form with Name input and a submit button.

import React, { useState } from 'react';

const App = () => {
    return (
        <div>
            <form className='form'>
                <div className='form-control'>
                    <label htmlFor='firstName'>Name: </label>
                    <input
                        type='text'
                        id='firstName'
                        name='firstName'
                    />
                </div>
                <button type='submit'>Add person</button>
            </form>
        </div>
  );
};

export default App;

Step 2: Set up state value

const [firstName, setFirstName] = useState('');

Step 3: Add 2 attributes in the input: value and onChange event listener

onChange event listener will fire the call back event listener every time we type the input

<input
    type='text'
    id='firstName'
    name='firstName'
    value={firstName}
    onChange={(e) => setFirstName(e.target.value)}
/>

Step 4: Submitting forms To submit the form in React, we can do the following steps:

  1. Use button or input as our submit buttons
<button>Submit</button>

or

<input type="submit" value="Submit" />
  1. We have 2 options:
  • Add an onSubmit event handler in <form> or
  • Add an onClick on button
<form onSubmit={handleSubmit}></form>
<button type="submit" onClick={handleSubmit}>Submit</button>
  1. Add handleSubmit function
const handleSubmit = (e) => {
    e.preventDefault();
    alert('You have submitted');
}

Putting it all together

import React, { useState } from 'react';

const App = () => {
    const [firstName, setFirstName] = useState('');

    const handleSubmit = (e) => {
        e.preventDefault();
        alert('You have submitted');
    }

    return (
        <div>
            <form className='form' onSubmit={handleSubmit}>
                <div className='form-control'>
                    <label htmlFor='firstName'>Name: </label>
                    <input
                        type='text'
                        id='firstName'
                        name='firstName'
                        value={firstName}
                        onChange={(e) => setFirstName(e.target.value)}
                    />
                </div>
                <button type='submit'>Add person</button>
            </form>
        </div>
  );
};

export default App;

III. Class Components

Forms in Class Components are slightly different from Functional Components.

1. Input fields

Here are steps to take an input element and transform it into a controlled component.

Step 1

To start, let’s define a class component, constructor, props, super props, state and render method.

import React from "react"

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {}
    }

    render() {
        return (
            <input />
        )
    }
}

export default App

Step 2

To turn an input field into a Controlled Component, we need to tie its value to the component state.

this.state = { value: ''}

Step 3

Next, we need to declare an event handler that will update the state input value whenever the form input value is changed.

The event.target.value attribute represents the new value of the inputs after it’s been changed:

handleChange(event) {
    this.setState({
        value: event.target.value
    })
}

Step 4

We need to bind the event handler to the component instance and also declare the initial state value:

constructor(props){
    super(props)
    this.state = {value: ''}
    this.handleChange = this.handleChange.bind(this)
}

Step 5

We then must attach the event handler to the <input> element in render method and set the input value equal to the state input value:

render(){
    return (
        <input
            type = "text"
            value = {this.state.value}
            onChange = {this.handleChange}
        />
    )
}

Putting it all together

import React from "react"

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {value: ''}
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        this.setState({
            value: event.target.value
        })
    }

    render() {
        return (
            <input
                type = "text"
                value = {this.state.value}
                onChange = {this.handleChange}
            />
        )
    }
}

Example

Here is a simple form with firstName and lastName as input text.

import React, {Component} from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: ""
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        this.setState({
            value: event.target.value
        })
    }

    render() {
        return (
            <form>
                <input
                    type="text"
                    value={this.state.firstName}
                    name="firstName"
                    placeholder="First Name"
                    onChange={this.handleChange}
                />
                <br />
                <input
                    type="text"
                    value={this.state.lastName}
                    name="lastName"
                    placeholder="Last Name"
                    onChange={this.handleChange}
                />
                <h2>{this.state.firstName} {this.state.lastName}</h2>
            </form>
        )
    }
}

export default App

2. Submitting form with Class Component

To submit the form, we can do the following steps:

Step 1: Use button or input as our submit buttons

<button>Submit</button>

or

<input type="submit" value="Submit" />

Step 2: Add an onSubmit event handler in <form>

<form onSubmit={this.handleSubmit}></form>

Step 3: Add handleSubmit function

handleSubmit(event) {
    e.preventDefault();
    alert('You have submitted: ' + this.state.value);
}

and bind handleSubmit:

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

3. TextArea fields

In React, textarea is a self-closing element, and we can use value attribute.

Therefore, we can update the value in the textarea by updating state.

<textarea value={}/>
class App extends React.Component {
    constructor(props){
        super(props)
        this.state = {value: 'Write your comment here'}

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

    handleChange(event) {
        this.setState({value: event.target.value})
    }

    handleSubmit(event) {
        e.preventDefault();
        alert('You have submitted: ' + this.state.value);
    }

    render(){
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    Comment:
                    <textarea
                        value = {this.state.value}
                        onChange = {this.handleChange}
                    />
                </label>
                <input type="submit" value="Submit" />
            </form>
        )
    }
}

The text area starts with some text because this.state.value is initialized in the constructor

4. Checkboxes

Checkboxes use a checked property instead of value in textarea or input.

Checkbox is either checked or not checked.

Step 1

Firstly, we add a checked property and it is determined by a Boolean (true or false) in state.

We also give it the name as checked.

<input
    type = "checkbox"
    name = "checked"
    checked = {this.state.checked}
/>

Step 2

Next, we set checked state as false, so it starts out as being unchecked.

this.state = {checked: false}

Step 3: Add an onChange event handler

<input
    type = "checkbox"
    name = "checked"
    checked = {this.state.checked}
    onChange = {this.handleChange}
/>

Step 4: Add handleChange function

handleChange(event) {
    this.setState({checked: event.target.checked})
}

and bind handleChange:

this.handleChange = this.handleChange.bind(this)

Putting it all together

class App extends React.Component{

    constructor(props) {
        super(props)
        this.state = {checked: false}
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event){
        this.setState({value: event.target.value})
    }

    handleSubmit(event) {
        e.preventDefault();
        alert('You have submitted: ' + this.state.value);
    }

    render(){
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    type = "checkbox"
                    name = "checked"
                    checked = {this.state.checked}
                    onChange = {this.handleChange}
                />
                <input type="submit" value="Submit" />
            </form>
        )
    }
}

5. Radio buttons

Radio button is the combination of input type text and checkbox. It uses both value and checked property.

Example: Creating 2 radio buttons for Male and Female options

Step 1: We set type as radio, add name and value property.

<form>
    <label>
        <input
            type="radio"
            name="gender"
            value="male"
        /> Male
    </label>
    <br />
    <label>
        <input
            type="radio"
            name="gender"
            value="female"
        /> Female
    </label>
</form>

Step 2

Next, we set gender state as an empty string.

this.state = {gender: ""}

Step 3: Add an onChange event handler

onChange={this.handleChange}

Step 4: Add handleChange function

handleChange(event) {
    this.setState({checked: event.target.checked})
}

and bind handleChange:

this.handleChange = this.handleChange.bind(this)

Step 5

For Male radio button, we set it’s checked if this.state.gender === "male"

<input
    type="radio"
    name="gender"
    value="male"
    checked={this.state.gender === "male"}
    onChange={this.handleChange}
/>

Similarly, for Female radio button, we set it’s checked if this.state.gender === "female"

<input
    type="radio"
    name="gender"
    value="male"
    checked={this.state.gender === "female"}
    onChange={this.handleChange}
/>

Putting it all together

class App extends React.Component{

    constructor(props) {
        super(props)
        this.state = {checked: false}

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

    handleChange(event) {
        this.setState({checked: event.target.checked})
    }

    handleSubmit(event) {
        e.preventDefault();
        alert('You have submitted: ' + this.state.value);
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="male"
                        checked={this.state.gender === "male"}
                        onChange={this.handleChange}
                    /> Male
                </label>
                <br />
                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="female"
                        checked={this.state.gender === "female"}
                        onChange={this.handleChange}
                    /> Female
                </label>
                <input type="submit" value="Submit" />
            </form>
        )
    }
}

6. Select tag

In HTML, <select> creates a drop-down list

<select>
    <option selected value="apple">apple</option>
    <option value="banana">banana</option>
    <option value="mango">mango</option>
    <option value="strawberry">strawberry</option>
</select>

In React, we use value attribute on the root select tag, instead of selected attribute.

Step 1:

  • Create a select box.
  • Add value, onChange handler, and name in select.
  • Make sure options have value.
<select
    value={this.state.value}
    onChange={this.handleChange}
    name="fruit"
>
    <option selected value="apple">apple</option>
    <option value="banana">banana</option>
    <option value="mango">mango</option>
    <option value="strawberry">strawberry</option>
</select>

Step 2: Next, we set which fruit is chosen at first.

this.state = {value: "apple"}

Step 3:

Add handleChange function

handleChange(event) {
    this.setState({checked: event.target.checked})
}

and bind handleChange:

this.handleChange = this.handleChange.bind(this)

Putting it all together

class App extends React.Component {

    constructor(props){
        super(props)
        this.state = {value: "apple"}

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

    handleChange(event){
        this.setState({value: event.target.value})
    }

    handleSubmit(event) {
        e.preventDefault();
        alert('You have submitted: ' + this.state.value);
    }

    render(){
        return (
            <form onSubmit={this.handleSubmit}>
                <label>Favorite Fruit:</label>
                    <select
                        value={this.state.value}
                        onChange={this.handleChange}
                        name="fruit"
                    >
                        <option value="apple">apple</option>
                        <option value="banana">banana</option>
                        <option value="mango">mango</option>
                        <option value="strawberry">strawberry</option>
                    </select>
                <input type="submit" value="Submit" />
            </form>
        )
    }
}

Select Components can also have their options dynamically generated using the map() method. Example:

class ControlledSelect extends React.Component{

    constructor(props) {
        super(props)
        this.state = {value: "apple"}
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        this.setState({value: event.target.value})
    }

    render() {
        let array = ["apple","banana","mango","strawberry"]
        let options = array.map( (item) =>
            <option value = {item}>{item}</option>
        )
        return (
          <select value={this.state.value} onChange={this.handleChange}>
            {options}
          </select>
        )
    }
}