⌨️ Инструкция: как создать форму в React

Показываем на примерах JS-кода, как создать форму с помощью контролируемых или неконтролируемых компонентов React и обработать состояние с помощью React хуков.

Формы, как способ взаимодействия с пользователем, являются важной частью любого приложения. Существуют формы для входа и регистрации, добавления товаров в корзину, обновления данных, создания или редактирования заказов и т. д.

Вот пример простой HTML-формы:

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

Давайте рассмотрим, как создаются формы в React.

Как создать форму в React с помощью контролируемых компонентов

Мы знаем, что такие HTML-элементы, как input, запоминают то, что мы вводим. Таким же образом можно использовать состояние компонента React для хранения данных элементов формы. Когда данные обрабатываются компонентом React, он называется контролируемым, а функционирование в нем завязано на состоянии компонента, а не на элементе DOM.

Давайте реализуем форму с помощью контролируемых компонентов, используя следующие элементы HTML: input, radio button, select dropdown.

Создадим компонент с тегом формы и один input:

import React, { Component } from "react";  
  
class ControlledFormComponent extends Component {  
  render() {  
    return (  
      <div>  
        <h3>Controlled Component</h3>  
        <br />  
        <form>  
          <label>Student Name: </label>  
          <input type="text" placeholder="enter student name" />  
        </form>  
      </div>  
    );  
  }  
}  
  
export default ControlledFormComponent; 

Выглядеть это будет так:

Контролируемый компонент формы

Создадим состояние в компоненте и повесим событие onChange на input, чтобы изменить состояние компонента при изменении значения input.

import React, { Component } from "react";  
  
class ControlledFormComponent extends Component {  
  
  constructor(props) {  
    super(props);  
    this.state = {  
      studentName: ""  
    };  
    this.onNameChangeHandler = this.onNameChangeHandler.bind(this);  
  }  
  
  onNameChangeHandler(e){  
    this.setState({  
      studentName: e.target.value  
    })  
  }  
  
  render() {  
    return (  
      <div>  
        <h3>Controlled Component</h3>  
        <br />  
        <form>  
          <label>Student Name: </label>  
          <input   
              type="text"   
              placeholder="enter student name"  
              onChange={this.onNameChangeHandler} />  
        </form>   
        <hr/>  
        <p>State of Component</p>        
          <pre>{JSON.stringify(this.state, null, 2) }</pre>       
      </div>  
    );  
  }  
}  
  
export default ControlledFormComponent;  

Мы создали состояние и добавили studentName в качестве свойства. После этого добавили обработчик onChange, который изменит состояние и забиндит его с событием onChange у input.

Таким же образом можно добавить еще один HTML-элемент и привязать его к состоянию компонента.

Добавим на нашу форму radio button и два новых свойства: пол и штат.

<label>Gender: </label>  
          <label>Male</label>  
          <input  
            type="radio"  
            name="gender"  
            value="male"  
            checked={this.state.gender === "male"}  
            onChange={this.onChangeHandler}  
          />  
          <label>Female</label>  
          <input  
            type="radio"  
            name="gender"  
            value="female"  
            checked={this.state.gender === "female"}  
            onChange={this.onChangeHandler}  
          />  
          <br />  
          <br />  
          <label>State: </label>  
          <select  
            name="state"  
            value={this.state.state}  
            onChange={this.onChangeHandler}  
          >  
            <option value="Maharashtra">Maharashtra</option>  
            <option value="Madhya Pradesh">Madhya Pradesh</option>  
            <option value="Karnataka">Karnataka</option>  
            <option value="West Bengal">West Bengal</option>  
          </select>  

Добавление отдельной функции обработки событий для каждого элемента – неправильный подход. Создадим для всех событий одну функцию:

onChangeHandler(e){  
    this.setState({  
      [e.target.name]: e.target.value  
    })  
  } 

Вот так выглядит готовый компонент:

import React, { Component } from "react";  
  
class ControlledFormComponent extends Component {  
  constructor(props) {  
    super(props);  
    this.state = {  
      studentName: "",  
      gender: "",  
      state: "Maharashtra"  
    };  
    this.onChangeHandler = this.onChangeHandler.bind(this);  
  }  
  onChangeHandler(e) {  
    this.setState({  
      [e.target.name]: e.target.value  
    });  
  }  
  render() {  
    return (  
      <div>  
        <h3>Controlled Component</h3>  
        <br />  
        <form>  
          <label>Student Name: </label>  
          <input  
            type="text"  
            name="studentName"  
            placeholder="enter student name"  
            onChange={this.onChangeHandler}  
          />  
          <br />  
          <br />  
          <label>Gender: </label>  
          <label>Male</label>  
          <input  
            type="radio"  
            name="gender"  
            value="male"  
            checked={this.state.gender === "male"}  
            onChange={this.onChangeHandler}  
          />  
          <label>Female</label>  
          <input  
            type="radio"  
            name="gender"  
            value="female"  
            checked={this.state.gender === "female"}  
            onChange={this.onChangeHandler}  
          />  
          <br />  
          <br />  
          <label>State: </label>  
          <select  
            name="state"  
            value={this.state.state}  
            onChange={this.onChangeHandler}  
          >  
            <option value="Maharashtra">Maharashtra</option>  
            <option value="Madhya Pradesh">Madhya Pradesh</option>  
            <option value="Karnataka">Karnataka</option>  
            <option value="West Bengal">West Bengal</option>  
          </select>  
        </form>  
        <br />  
        <hr />  
        <p>State of Component</p>  
        <pre>{JSON.stringify(this.state, null, 2)}</pre>  
      </div>  
    );  
  }  
}  
  
export default ControlledFormComponent;  
Компонент в действии

Использование хуков React

Состояние формы можно обрабатывать и с помощью хуков. Чтобы хранить состояние в компоненте, существует useState(). Создадим простую форму с одним инпутом и обработаем ее с помощью хука:

import React, { useState } from 'react';  
  
export default function ControlledFormWithHook() {  
  const [name, setName] = useState('');  
  
  return (  
    <div>  
      <form>  
        <label>Name:</label>  
        <input type="text" onChange={(e) => setName(e.target.value)} />  
      </form>  
      <br />  
      Name is: {name}  
    </div>  
  );  
}  
Форма с использованием хуков

Как создать форму в React с помощью неконтролируемых компонентов

Мы знаем, что HTML-элементы сохраняют собственное состояние и обновляют его при изменении входного значения. То есть мы можем получить прямой доступ к значению HTML-элемента без сохранения состояния компонента. Когда данные обрабатываются элементами DOM, это можно назвать неконтролируемым компонентом. React позволяет напрямую получить ссылку на элемент DOM и хранить в нем состояние компонента.

В некоторых случаях мы должны использовать неконтролируемый компонент, например, когда хотим добавить выбор файла: <input type="file"/>.

Возьмем тот же пример и немного переделаем с помощью React.createRef() API.

import React, { Component } from "react";  
  
export default function UncontrolledFormComponent() {  
  let inputRef = React.createRef();  
  let name = "";  
  const handleClick = e => {  
    e.preventDefault();  
    alert("Name is: " + inputRef.current.value);  
  };  
  
  return (  
    <div>  
      <h3>Uncontrolled Form Component</h3>  
      <form>  
        <input type="text" ref={inputRef} />  
        <button style={{ margin: "8px" }} onClick={handleClick}>  
          Submit  
        </button>  
      </form>  
    </div>  
  );  
} 

Когда вы нажимаете на Submit, открывается alert со значением, которое было введено в текстовом поле.

Работа с неконтролируемым компонентом
***

Мне нужно оперативно погрузиться во фронтенд. Какой вариант самый быстрый и качественный?

Если 15 лет назад для того, чтобы называть себя фронтенд-разработчиком достаточно было знать HTML, CSS и JavaScript, то сейчас фронтенд-разработка почти не отстает от бэкенд-разработки по количеству фреймворков и сложности стеков. Самый быстрый и качественный вариант — получить знания из первых рук от преподавателей со стажем. Поэтому мы запустили курс «Frontend Basic: принцип работы современного веба», на котором вы:

  • освоите стек технологий, который позволит начать работать в любой компании на любом проекте;
  • сверстаете свой первый адаптивный макет с учетом семантики и множества декоративных элементов на HTML и CSS;
  • поймете, как с помощью JavaScript разрабатывать пользовательские интерфейсы;
  • разберетесь, как JavaScript используется в работе с backend и создадите свой первый обмен данными сервером;
  • углубитесь в более сложную разработку на React.js и напишете свой интернет-магазин;
  • изучите основные команды для работы с GIT, важнейшего инструмента для работы в любой команде.

Источники

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ