📜 ⬆️ ⬇️

React Training Course, Part 24: Second Form Work

Today we will continue the conversation about using forms in React. Last time we considered the features of the interaction of components and text fields. Here we will discuss working with other form elements.

image

→ Part 1: Course Overview, React, ReactDOM, and JSX Reasons
→ Part 2: Functional Components
→ Part 3: Component Files, Project Structure
→ Part 4: Parent and Child Components
→ Part 5: Getting Started on a TODO Application, Basics of Styling
→ Part 6: Some of the features of the course, JSX and JavaScript
→ Part 7: Inline Styles
→ Part 8: continued work on the TODO application, familiarity with the properties of components
→ Part 9: Component Properties
→ Part 10: Workshop on working with the properties of components and styling
→ Part 11: dynamic markup generation and the map array method
→ Part 12: workshop, the third stage of work on the TODO application
→ Part 13: Class Based Components
→ Part 14: Workshop on Class Based Components, Component State
→ Part 15: workshops on working with the state of components
→ Part 16: the fourth stage of the work on the TODO application, event handling
→ Part 17: the fifth stage of working on a TODO application, modifying the state of components
→ Part 18: Sixth Stage of Work on a TODO Application
→ Part 19: Component Life Cycle Techniques
→ Part 20: The first lesson in conditional rendering.
→ Part 21: the second lesson and workshop on conditional rendering
→ Part 22: Seventh stage of work on a TODO application, loading data from external sources
→ Part 23: First Form Lesson
→ Part 24: Second Form Lesson

Lesson 42. Working with forms, part 2


→ Original
')
In this lesson, we will talk about fields for entering multi-line text, about flags, about switches (they are also called “radio buttons”) and about fields with lists. To date, we considered only the work with the usual text input fields.
Here is the App component code from which we will start today's experiments:

 import React, {Component} from "react" class App extends Component {   constructor() {       super()       this.state = {           firstName: "",           lastName: ""       }       this.handleChange = this.handleChange.bind(this)   }     handleChange(event) {       const {name, value} = event.target       this.setState({           [name]: 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}               />                             {                   /**                    *    :                    *                    * <textarea />                    * <input type="checkbox" />                    * <input type="radio" />                    * <select>  <option>                    */               }                             <h1>{this.state.firstName} {this.state.lastName}</h1>           </form>       )   } } export default App 

Here is how the application page in the browser at this stage of work.


Application page in the browser

Forms usually contain not only fields into which they enter short strings. When equipping forms with other elements, working with them in React becomes a bit more complicated, although there is nothing special about it.

In the code above, there is a commented out snippet that lists the elements we will talk about. Let's start with the input field for multiline text - the textarea element. It’s probably the easiest to understand how to work with him. If you have previously used ordinary HTML forms, have already used this element, you know that this is not a self-closing tag, as was the case with the input element. He has opening and closing parts.
Add this element to the form by inserting the following code immediately after the comment:

 <br /> <textarea></textarea> 

If you now look at the application page, you can see how the multiline text input field appeared on it.


The field for entering text on the page

As you can see, this field is slightly higher than ordinary fields, the user can change its size using the marker in its right bottom. Thanks to the rows and cols you can specify its size when describing this element. In plain HTML, if it is necessary that after the output of this field some text already exists in it, this is done by entering the necessary text between the opening and closing tags of the element. In React, work with such elements is made as similar as possible to work with input elements, which we talked about last time. Namely, in React, the textarea tag is self-closing. That is, the code for displaying the field on the page can be changed as follows:

 <textarea /> 

In this tag, you can use the value attribute, and working with it is carried out in the same way as with the same attribute of ordinary text fields. Due to this, uniformity is achieved in working with different elements, and, in addition, it is easier to update the contents of the fields by updating the state properties associated with such fields. We give the state of the field code to this form:

 <textarea value={"Some default value"}/> 

This will cause the specified text to appear in the field when it is displayed on the page.


Text appearing in the field

We will return to working with the field for entering multi-line text, but for now let's talk about the checkboxes. A checkbox is an input control, the type of which is a checkbox . Here is its description:

 <input type="checkbox" /> 

This is what the checkbox described by this markup looks like on the page.


Checkbox

The main feature of this control is the fact that the value attribute is not used when working with it. It is used in order to provide the user with a choice of some two options, one of which corresponds to the checkbox and the other to the unchecked. To track whether a checkbox is selected or cleared, the checked attribute is used, which is described by a Boolean value. As a result, the flags usually correspond to logical properties stored in the state.

We give the state of the component to this form:

 this.state = {   firstName: "",   lastName: "",   isFriendly: true } 

The flag description code will be changed as follows:

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

After that, the checked box will be displayed on the page.


Checkbox

True, now he will not respond to clicks on it. The fact is that the checkbox is tied to the corresponding variable stored in the state, as a result of an attempt, in our case, to uncheck it, React, checking the state, and detecting that the isFriendly property isFriendly set to true does not allow this. At the same time, a warning will be displayed in the console that we have not provided a mechanism for changing the field ( onChange event onChange ) and it is displayed in the “read only” state.


Console warning

We may well write a special method for working with a flag, but in the code of our component there is already a handleChange() method. Now it is used to work with text fields. We will think about how to use it to work with the flag. To do this, first assign the above method as a handler for the onChange event of the checkbox and assign a checkbox the name corresponding to the name of the state property associated with the checkbox. In addition, we will sign the checkbox using the label tag:

 <label>    <input       type="checkbox"       name="isFriendly"       checked={this.state.isFriendly}       onChange={this.handleChange}   /> Is friendly? </label> 

In the handleChange() method, the code of which is shown below, we, when working with text fields, found out the name of the element ( name ) and its contents ( value ), and then updated the state by writing to it what the field with a specific name in its value attribute:

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

Now we need to figure out how to deal with the flag, which has no value attribute. It has only the checked attribute, which can only be true or false . As a result, in order to use the handleChange() method to work with a flag, we need to check whether the element for which this handler is called is a flag. To perform this check, recall that the type (element) of the input element that represents the check box is set to checkbox . To check this value, you can access the type property of the event.target element. Extract this property from the event.target , as well as the property checked , using the following construction:

 const {name, value, type, checked} = event.target 

Now we can check the value of the type constant and find out whether the element for which the event handler is called is a flag. If this is the case, we will write to the state that turned out to be in the checked constant. Don't forget to keep the code responsible for working with text fields. As a result, the handleChange() code handleChange() take the following form:

 handleChange(event) {   const {name, value, type, checked} = event.target   type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value }) } 

After that, check the work flag.


Check the operation of the checkbox

As you can see, now it can be removed and installed. At the same time, the work of text fields is not broken. A notification regarding the check box has disappeared from the console, but a notification is displayed there regarding the multiline text entry field. Modify the code describing this field as follows:

 <textarea   value={"Some default value"}   onChange={this.handleChange} /> 

This will lead to the disappearance of the notification, although we did not implement the other mechanisms that allow working with this field by means of the component (did not specify a name for the field, did not add the corresponding property to the state). You can realize these opportunities by yourself. Now let's talk about the switches.

They can be represented as a combination of input elements of the text and checkbox types. What is meant here is that the switches have both a value attribute and a checked attribute. Add a couple of switches to our form by creating their code based on the flag description code. Here's what it looks like:

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

We created this code based on the flag description code and didn’t edit anything yet. Therefore, the switches behave strangely. In particular, if the box is unchecked, then both the switches are in the "off" state, and if the box is checked, one of them turns out to be "on". Such errors can be prevented by carefully referring to the code of elements in the event that it is created on the basis of the code of already existing elements. Now we fix it.
Notice that these two elements have the same name, gender . Switches with the same name form a group. Selected can be only one switch included in such a group.

When setting switches, one cannot simply indicate that their checked value is set, say, to true , if a certain state property equals true . Switches must support a synchronized change of their own state within a group. Instead, the checked value of the switches is set by condition. In our case, this condition will be represented by comparing the state property this.state.gender with the line male or female . In the switch description code, it looks like this:

 <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> 

Now add a new property to the state, gender , initializing it with an empty string:

 this.state = {   firstName: "",   lastName: "",   isFriendly: false,   gender: "" } 

After that, the switches will work regardless of the checkbox. Add a second-level header to the code displayed by the component, which shows which switch is selected:

 <h2><font color="#3AC1EF">You are a {this.state.gender}</font></h2> 

There probably should be some kind of conditional rendering mechanism. This will allow, when you open the page, when none of the switches are selected, to make sure that the text You are a would not appear on it, but we will not do this, although you can easily implement it yourself. Now let's look at what we did.


Switches on the application page

Everything we talked about here can seem rather complicated. In particular, this concerns memorizing the features of different controls. In order to simplify work with forms, you can use specialized libraries. For example, the formik library. This library greatly simplifies the process of developing forms in React-applications.

Now let's talk about the list fields.

In normal HTML, the following constructions are used to describe combo boxes:

 <select>   <option></option>   <option></option>   <option></option> <select/> 

React uses a similar approach, although, as is the case with other elements, the value attribute is used. This makes it easy to figure out exactly which element of the list is selected, and, in addition, it facilitates working with the state of the component.

Suppose we want to create a combo box that allows the user to select his favorite color. To do this, you can put the following construction in the value attribute of the select element: value={this.state.favColor} . This will get those values ​​that the user will choose. Now add favColor to the state:

 this.state = {   firstName: "",   lastName: "",   isFriendly: false,   gender: "",   favColor: "blue" } 

Next, let's equip the combo box with the onChange event onChange and give it a name. Also, assign the value values ​​to the options elements of the combo box and enter the text that will be displayed in the field.

Here is what a customized select element looks like with a caption:

 <label>Favorite Color:</label> <select   value={this.state.favColor}   onChange={this.handleChange}   name="favColor" >   <option value="blue">Blue</option>   <option value="green">Green</option>   <option value="red">Red</option>   <option value="orange">Orange</option>   <option value="yellow">Yellow</option> </select> 

Now add another inscription to the form that displays the user's favorite color:

 <h2><font color="#3AC1EF">Your favorite color is {this.state.favColor}</font></h2> 

It's time to try out the combo box.


Combo box

As you can see, although our form does not shine with the delights of design, the controls placed on it work as expected.

Due to the way the Reactor Controls API is organized, it is easy to make the same handler used to process their events. This is the scheme of work used in our case. The only feature of our handleChange() handler is that we have to handle flag events in a special way.

Now let's talk about sending the form or about processing the values ​​entered into it after completing it. There are two approaches to the implementation of such actions. When using any of them, the form should be equipped with the button:

 <button>Submit</button> 

In HTML5, if a button element is found in the form, it will act as the old input element with the type submit . If this button is onSubmit event of the onSubmit form itself will be triggered. If you need to do something after completing the form, you can add an onClick event onClick to the button, but, for example, I personally prefer to handle such events at the form level, assigning an onSubmit event handler to onSubmit :

 <form onSubmit={this.handleSubmit}> 

The method used as the handler for this event has not yet been written. This is a regular event handler, which, for example, when accessing a certain API, sends it form data.

Results


In this lesson, we end the conversation about working with forms in React. The next time you are waiting for practical work on this topic.

Dear readers! If you tried to use the formik library to create forms in React, please tell us about it.

Source: https://habr.com/ru/post/444356/


All Articles