Формы


HTML компоненты, такие как input, textarea, и option отличаются от других неуправляемых компонентов, потому что они могут быть видоизменены посредством взаимодействия с пользователем.
Существует два типа контурных компонентов:
  • Контролируемые компоненты
  • Неконтролируемые компоненты

Можно перейти непосредственно к примерам.

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


Контролируемый контурный компонент обеспечивает свойство prop «value». Контролируемый компонент не поддерживает своего собственного внутреннего состояния; генерация компонента основана на функциях props.
render() {
  return (
    <input
      type="text"
      value="Hello!" />
  );
}



Если вы попытаетесь запустить этот пример, вы увидите, что входные данные не изменяются по мере ввода. Это происходит потому, что компонент признал «value» входных данных всегда выводить «Hello!».
Чтобы обновить значение в ответ на ввод пользователя, вы должны использовать событие «onChange», чтобы сохранить новое значение, а затем передать его в функцию prop «value» входных данных:
class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

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

  handleSubmit(event) {
    alert('Text field value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <input type="text"
          placeholder="Hello!"
          value={this.state.value}
          onChange={this.handleChange} />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);



В этом примере, мы принимаем значение, указанное пользователем и обновляем свойство prop «value» компонента "". Этот шаблон позволяет легко реализовывать интерфейсы, которые реагируют на проверки или взаимодействия с пользователем. Например:

handleChange(event) {
    this.setState({
      value: event.target.value.substr(0, 140)
    });
  }



Это подтвердит ввод данных пользователем и усечет значение первых 140 символов.
Контролируемые компоненты также позволяют нам сбросить входные данные на произвольные значения путем установки программного уровня:

handleClearClick() {
    this.setState({
      value: ''
    });
  }



Потенциальные проблемы с флажками и переключателями
Имейте в виду, что в попытке нормализовать изменение обработки для флажков и переключателей, React реагирует на событие браузера «click», чтобы реализовать событие «onChange».
По большей части это работает, как ожидалось, за исключением, когда запрос «preventDefault» в обработчике события «change». «preventDefault» предохраняет браузер от обновления входных данных, даже если «checked» переключается. Это можно решить посредством удаления запроса «preventDefault », или установки переключения «checked» в «setTimeout».

Неконтролируемые компоненты


Форма-компоненты, которые не обеспечивают prop «value», являются неконтролируемыми. 
Приведенный ниже пример показывает управление "" при помощи пустого значения. Любой пользовательский ввод будет немедленно отражен посредством представленного элемента. Неконтролируемый компонент управляет своим собственным состоянием.

render() {
    return <input type="text" />;
  }



Если вы хотели получить обновления значения, вы могли бы использовать событие «onChange», как и в случае с контролируемыми компонентами.

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

  handleChange(event) {
    // Note: with uncontrolled inputs, you don't
    // have to put the value in the state.
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('Text field value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <input
          type="text"
          placeholder="Hello!"
          onChange={this.handleChange} />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);



Несмотря на то, что данный пример дает оценку программному уровню, далее мы сможем прочитать его в «handleSubmit()», неконтролируемые формы-компоненты этого не требуют. Вы можете полностью опустить обработчик «onChange» и, вместо этого, прочитать значение входных данных, используя ссылки ОМД, дополнительную функцию мы обсудим позже.

Значения по умолчанию
Для инициализации неконтролируемого компонента с не пустым значением, вы можете указать свойство prop «defaultValue».

render() {
    return <input type="text" defaultValue="Hello!" />;
  }




Также, "<input type="checkbox">" и "<input type="radio">" поддерживают "defaultChecked", а "<select>" поддерживает "defaultValue".



Интерактивные props


Контурные компоненты поддерживают несколько свойств props, которые страдают от взаимодействия с пользователем:

«value», поддерживаемая компонентами «input» и «textarea».

«checked», поддерживаемая компонентами «input» следующих типов: «checkbox» или «radio».
«selected», поддерживаемая компонентами «option».
В HTML значение «textarea» задается через дочерний модуль. В React вместо него используйте «value». 
Контурные компоненты позволяют перехватить изменения путем установки обратного запроса для свойства prop «OnChange».
Опора «OnChange» работает во всех браузерах, чтобы отвечать на действия пользователя, когда:
Изменяется свойство «value» компонента «input» или «textarea».
Изменяется состояние «checked» компонента «input».
Изменяется состояние «selected» компонента «option».
Как и все события DOM, опора «OnChange» поддерживается на всех неуправляемых компонентах и может быть использована для отслеживания изменяющихся событий.

Примечание:
Для компонентов «input» и «textarea», обычно должен использоваться «onChange» вместо встроенного в DOM обработчика событий «oninput».


Дополнительные темы

Для чего нужны контролируемые компоненты?


Использование в React контурных компонентов, таких как "", может повлечь за собой некоторые проблемы, которых можно избежать при написании традиционных форм HTML.

Например, в HTML:
input type=«text» name=«title» value=«Untitled»


Это генерирует входные данные, установленные значением «Untitled». Когда пользователь обновляет входные данные, свойство узла «value» изменится. Однако «node.getAttribute('value')» будет возвращать значение, которое использовалось во время инициализации, «Untitled».

В отличие от HTML, компоненты React должны отображать программный уровень вкладки в любое время, а не только во время инициализации. Например, в React:

 render() {
    return <input type="text" name="title" value="Untitled" />;
  }



Так как этот метод описывает выборку в любой момент времени, значение входных данных всегда должно быть «Untitled».

Для чего нужна команда «textarea»?
В случае с HTML, текстовое поле позволяет разработчикам легко поставить многострочные значения. Однако, так как React относится к JavaScript, ограничения исчезли и мы можем использовать "\N", если хотим, чтобы текст пошел с новой строки. Когда есть «value» и «defaultValue» роль дочерних модулей неоднозначна. По этой причине вам не обязательно использовать дочерние элементы при команде «textarea»:

 <!-- Don't do this in React. -->
  <textarea name="description">This is the description.</textarea>



Если вы все же решили использовать дочерние модули, они будут вести себя как «defaultValue».
Зачем выбирать значение?

Выбранные «option» в HTML «select» обычно указываются посредством атрибута параметра «selected». В React мы назначаем компонент «select» определенной величины, путем передачи свойства «value»:

<textarea name="description" value="This is a description." />



Для создания неконтролируемого компонента, используйте «defaultValue».

<select value="B">
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>



Примечание:
Вы можете передать массив в «value», который позволяет выбрать несколько вариантов в теге «select»:<select multiple={true} value={['B', 'C']}>.


Императивные операции


Если вам необходимо выполнить операцию императивно, вы должны получить ссылку на узел ОМД. Например, если вы хотите императивно отправить форму, один подход будет связан с прикреплением «ref» к  элементу «form»  и вызову вручную «form.submit()».

Примеры
Контролируемые входные данные

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

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

  handleSubmit(event) {
    alert('Text field value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <input
          type="text"
          placeholder="edit me"
          value={this.state.value}
          onChange={this.handleChange}
        />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);




Контролируемая команда «Textarea»

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

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

  handleSubmit(event) {
    alert('Textarea value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <textarea
          name="description"
          value={this.state.value}
          onChange={this.handleChange}
        />
        <br />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);



Контролируемое значение

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

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

  handleSubmit(event) {
    alert('Select value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <select value={this.state.value} onChange={this.handleChange}>
          <option value="A">Apple</option>
          <option value="B">Banana</option>
          <option value="C">Cranberry</option>
        </select>
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);




Неконтролируемый input

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

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

  handleSubmit(event) {
    alert('Radio button value is: ' + this.state.value);
  }

  render() {
    return (
      <div>
        <label>
          <input
            type="radio"
            name="choice"
            value="A"
            onChange={this.handleChange} />
          Option A
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="choice"
            value="B"
            onChange={this.handleChange}
            defaultChecked={true} />
          Option B
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="choice"
            value="C"
            onChange={this.handleChange} /> 
          Option C
        </label>
        <br />
        <br />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);




Неконтролируемый type=«radio»

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {checked: {'A': false, 'B': true, 'C': false}};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    const value = event.target.value;
    // Copy the object so we don't mutate the old state.
    // (This requires an Object.assign polyfill):
    const checked = Object.assign({}, this.state.checked)
    if (!checked[value]) {
      checked[value] = true;
    } else {
      checked[value] = false;
    };
    this.setState({checked});
  }

  handleSubmit(event) {
    alert('Boxes checked: ' +
      (this.state.checked.A ? 'A ' : '') +
      (this.state.checked.B ? 'B ' : '') +
      (this.state.checked.C ? 'C' : '')
    );
  }

  render() {
    return (
      <div>
        <label>
          <input
            type="checkbox"
            value="A"
            onChange={this.handleChange} /> 
          Option A
        </label>
        <br />
        <label>
          <input
            type="checkbox"
            value="B"
            onChange={this.handleChange}
            defaultChecked={true} /> 
          Option B
        </label>
        <br />
        <label>
        <input
          type="checkbox"
          value="C"
          onChange={this.handleChange} /> 
          Option C
        </label>
        <br />
        <br />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);