React form processing

Keywords: Front-end React

In React, the form is divided into two parts: controlled components and uncontrolled components.

4.7.1 controlled components

We know that form elements in HTML can input data (or delete), that is, they have their own variable state. For example, in a text box, you can enter or delete content in the text box, and the entered content can be called variable status. This state is maintained by HTML form elements.

However, in React, we know that variable states are usually saved in state and can only be modified through the setState method.

At this time, there is a conflict with the form elements in HTML in the maintenance of state. In order to solve this conflict, React binds state to the value of the form element, and the value of the form element is controlled by the value of state.

Therefore, we call the form elements whose values are controlled by React as controlled components.

import React,{Component}from 'react'
class App extends Component{
    state={
        num:10
    }
    handleChange=e=>{
        this.setState({
            num:e.target.value
        })
    }
    render(){
        return (
            <div>
                {this.state.num}
                <input type="text" value={this.state.num} onChange={this.handleChange}/>
            </div>
        )
    }
}
export default App

Here, the state state in React is bound to the value attribute in the text box, and then an onChange is added to the text box. When a value is entered in the text box, the handleChange method will be called. In this method, the value entered in the text box is obtained through e.target.value, and then the state is given again, At this time, the num in the state displayed in div has also changed accordingly.

Here are some examples of controlled components:

Rich text box case

The implementation of rich text box is basically the same as that of text box. The code is as follows:

import React,{Component}from 'react'
class App extends Component{
    state={
        content:'Hello'
    }
    handleChange=e=>{
        this.setState({
            content:e.target.value
        })
    }
    render(){
        return (
            <div>
                {this.state.content}        
                <textarea  value={this.state.content}  onChange={this.handleChange}></textarea>
            </div>
        )
    }
}
export default App

Drop down box application

import React,{Component}from 'react'
class App extends Component{
    state={
        city:'shanghai'
    }
    handleChange=e=>{
        this.setState({
            city:e.target.value
        })
    }
    render(){
        return (
            <div>
                {this.state.city}        
                <select value={this.state.city} onChange={this.handleChange}>
                    <option value='beijing'>Beijing</option>
                    <option value='shanghai'>Shanghai</option>
                    <option value='guangzhou'>Guangzhou</option>
                </select>
            </div>
        )
    }
}
export default App

In the above code, the city value in the defined state is' shanghai 'and bound with the value attribute of the select tag. At this time, the item' shanghai 'will be displayed by default. When different options in the drop-down box are selected, the handleChange method corresponding to onChange will be executed, in which the value value of the item selected by the user will be obtained, and then the state will be re assigned

Check box apply
 

import React,{Component}from 'react'
class App extends Component{
    state={
        isChecked:true
    }
    handleChange=e=>{
        this.setState({
            isChecked:e.target.checked
        })
    }
    render(){
        return (
            <div>      
             check box<input type="checkbox" checked={this.state.isChecked} onChange={this.handleChange}/>
            </div>
        )
    }
}
export default App

Note that what you get here is the checked

After updating the status of the check box, you want to view the corresponding status value immediately.
 

import React, { Component } from "react";
class ControlComponent extends Component {
  state = {
    isChecked: true,
  };
  handleChange = (e) => {
    this.setState({ isChecked: e.target.checked }, () => {
      console.log(this.state.isChecked);
    });
  };
  render() {
    return (
      <div>
        check box
        <input
          type="checkbox"
          checked={this.state.isChecked}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}
export default ControlComponent;

The above code adds a second parameter to the setState method. The second parameter is a callback function, which will be called immediately after the status update is successful

Controlled component update state process

Through the previous cases, we can summarize the process of updating state of React controlled components

(1) You can set the default value of the form in the initial state.

(2) Add onChange to the form, and when the value in the form changes, the function specified by onChange will be called.

(3) Obtain the changed state of the form through the composite event object in the corresponding processing function, and update the corresponding state

(4) setState triggers the re rendering of the page to complete the update of the value in the form.

In fact, through the analysis of the whole process, we can find that the data in the form comes from state at first, that is, binding state to the form, which is actually one-way data binding. Then, we update the new data entered in the form back to state through the method corresponding to onChange event, so as to complete two-way data binding.

Compared with the native form, the mode of the controlled component is indeed much more complex. The above steps will be performed every time the data in the form changes, but it will be easier to perform some special operations on the values in the form.

For example, the following case requires that the value entered in the text box cannot exceed 60

import React,{Component}from 'react'
class App extends Component{
    state={
        num:10
    }
    handleChange=e=>{
        this.setState({
            // Get the value entered by the user in the text box. If it exceeds 60, the corresponding state value is 10. At this time, 10 is still displayed in the text box
            num:e.target.value>60?10:e.target.value
        })
    }
    render(){
        return (
            <div>
                {this.state.num}
                <input type="text" value={this.state.num} onChange={this.handleChange}/>
            </div>
        )
    }
}
export default App

Form processing optimization

Now, let's think about a problem. If a page needs more form elements, how should we deal with it?

If you still follow the previous method, you need to write a lot of methods. This is more troublesome. Therefore, you can package the processing of multiple form elements into one method, but the problem is that different form elements need to be processed in this method. How should you distinguish them?

For the problems to be considered at this time, let's take a look at the specific implementation steps:

-Add the name attribute to the form element (to distinguish which form it is), and the name is the same as state (to update the data)
-Obtain the corresponding value according to the form content
-In the change event handler, use [name] to modify the corresponding state

Through specific implementation steps:

It can be found that in order to distinguish the form elements processed in the method, it needs to be done through the name attribute.

The specific code is as follows:
 

import React,{Component}from 'react'
class App extends Component{
    state={
        num:10,
        content:'Hello',
        city:'shanghai',
        isChecked:true
    }
    handleChange=e=>{
        // Gets the current element
        const target = e.target;
        //Determine the type of element
      const value=target.type==='checkbox'?target.checked:target.value;
      console.log(value);
      //Get name
      const name=target.name;
        this.setState({
            [name]:value
        })
    }
    render(){
        return (
            <div>
                {this.state.num}
                {this.state.content}
                {this.state.city}       
                 <hr/>
               <input type="text" name="num" value={this.state.num} onChange={this.handleChange}/>
                <textarea  value={this.state.content} name="content"  onChange={this.handleChange}></textarea>
                <select value={this.state.city} name="city" onChange={this.handleChange}>
                    <option value='beijing'>Beijing</option>
                    <option value='shanghai'>Shanghai</option>
                    <option value='guangzhou'>Guangzhou</option>
                </select>
                check box<input type="checkbox" name="isChecked" checked={this.state.isChecked} onChange={this.handleChange}/>
            </div>
        )
    }
}
export default App

Uncontrolled components

The uncontrolled component is no longer controlled by the state. It needs to use the element DOM method to obtain the form element value with the help of ref.

ref is used to obtain the DOM, so this method is a direct operation of the dom.

The specific implementation steps are as follows:

-Call the React.createRef() method to create a ref object
-Add the created ref object to the text box
-Get the value of the text box through the ref object

The code demonstration is as follows: (click the button to get the value in the text box)
 

import React,{Component}from 'react'
class App extends Component{
    constructor(){
        super()
        //Create ref and assign the created ref to the current this
      this.txtRef= React.createRef()
    }
    getValue=()=>{
        //Get the value in the text box (note that current needs to be added here)
        console.log(this.txtRef.current.value)
    }
    render(){
        return (
            <div>
                {/* Associate the created ref with the current text box */}
                <input type="text" ref={this.txtRef}/>
                <button type="button" onClick={this.getValue}>Gets the value in the text box</button>
            </div>
        )
    }
}
export default App

Posted by nodi on Wed, 17 Nov 2021 20:21:32 -0800