9. Form Processing

Posted by aeboi80 on Tue, 18 Jun 2019 02:36:20 +0200

9. Form Processing

HTML form elements are somewhat different from other DOM elements in React, because form elements naturally retain some internal state. For example, this form in pure HTML format accepts a single name:

<form>
    <label>
        Name:
        <input type="text" name="name" />
    </label>
    <input type="submit" value="Submit" />
</form>

This form has the default HTML form behavior of browsing to a new page when the user submits the form.
If you want this behavior in React, it can work. However, in most cases, it is convenient to use JavaScript functions to process form submission and access the data entered by users in the form. The standard way to do this is to use a technology called "controllable components".

Controllable Component

In HTML, form elements such as <input>, <textarea> and <select> usually maintain their own state and update it based on user input. In React, variable state is usually stored in the component's state attribute and updated only with setState().

We can combine the two by making React state the "only source of truth". Subsequent users are still controlled by React components when entering the form. The input form elements whose values are controlled by React in this way are called "controllable components".

For example, if we want the previous example log to record the name when submitted, we can use the form as a controllable component:

import React from 'react';
import ReactDOM from 'react-dom';

class NameForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: ''};
        this.change = this.change.bind(this);
        this.submit = this.submit.bind(this);
    }

    change(e) {
        this.setState({value: e.target.value});
    }

    submit(e) {
        e.preventDefault();
        console.log('A name was submitted: ', this.state.value);
    }

    render() {
        return (
            <form onSubmit={this.submit} >
                <label>
                    Name:
                    <input type="text"
                           value={this.state.value}
                           onChange={this.change}
                    />
                </label>
                <input type="submit" value="Submit" />
            </form>
        )
    };
}
ReactDOM.render(
    <NameForm/>,
    document.getElementById('root')
);

Because the value attribute is set on the form element, the value displayed will always be this.state.value, making React state its true source of value. Because change runs and updates React state at each keystroke, the value displayed will be updated as the user types.

With controlled components, each state variable will have an associated processing function when modifying or validating user input directly. For example, if we want to enforce that all name s are written in capital letters, we can write change as follows:

change(e) {
    this.setState({value: e.target.value.toUpperCase()});
}

textarea tag

In HTML, the sub-element of the <textarea> element is its text content:

<textarea>
    Hello there, my name is zhangyatao!
</textarea>

In React, <textarea> is changed to use the value attribute. In this way, a form that uses < textarea > can be very similar to a form that uses a single line of input:

class EssayForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: 'Please fill in one that you like. dom element'};
        this.change = this.change.bind(this);
        this.submit = this.submit.bind(this);
    }
    change(e) {
        this.setState({value: e.target.value});
    }
    submit(e) {
        e.preventDefault();
        console.log('Something was submitted:', this.state.value);
    }
    render() {
        return (
            <form onSubmit={this.submit}>
                <label>
                    Name:
                    <textarea value={this.state.value} onChange={this.change} />
                </label>
                <input type="submit" value="Submit" />
            </form>
        );
    }
}

Note that this.state.value is initialized in the constructor, so textarea displays the text by default.

select tag

In HTML, <select> creates a drop-down list. For example, this HTML creates a drop-down list:

<select>
    <option value="fruit">fruit</option>
    <option value="lime">lime</option>
    <option selected value="coconut">coconut</option>
    <option value="mango">mango</option>
</select>

Note that the coconut option is selected by default because of the selected attribute.
In React, the value attribute is usually used on the root select tag instead of the selected attribute. This is convenient in controlled components because you only need to update it in one place. For example:

import React from 'react';
import ReactDOM from 'react-dom';

class FlavorForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: 'coconut'};
        this.change = this.change.bind(this);
        this.submit = this.submit.bind(this);
    }

    change(e) {
        this.setState({value: e.target.value});
    }

    submit(e) {
        e.preventDefault();
        console.log('What you like is:', this.state.value);
    }

    render() {
        return (
            <form onSubmit={this.submit}>
                <label>
                    //Please choose a fruit you like.
                    <select value={this.state.value} onChange={this.change}>
                        <option value="fruit">fruit</option>
                        <option value="lime">lime</option>
                        <option value="coconut">coconut</option>
                        <option value="mango">mango</option>
                    </select>
                </label>
                <input type="submit" value="submit"/>
            </form>
        );
    }
}
ReactDOM.render(
    <FlavorForm/>,
    document.getElementById('root')
);

Overall, this makes < input type = text >, < textarea > and < Select > very similar. - They all accept a value attribute, which you can use to implement controllable components.

Options for Controllable Components

Using controlled components can sometimes be tedious because you need to write event handlers for data changes each time and manage all input states through React components.  
This can become particularly annoying when you convert existing projects into React or integrate React applications with non-React libraries.
In these cases, you may want to choose uncontrollable components (explained in detail later) as an alternative technology for implementing input forms.

Topics: React Attribute Javascript