Это седьмая часть моих заметок о Руководстве по ReactJS для начинающих от egghead.io.

Создание базовых форм с помощью React

В этом разделе мы обсудим, как создать базовую форму с помощью React, как предотвратить поведение отправки по умолчанию с помощью onSubmit и как получить значения из формы.

Предотвращение поведения по умолчанию

Давайте начнем с базовой кнопки ввода и отправки в элементе формы:

class NameForm extends React.Component {
  render() {
    return (
    <form>
      <label>
        Name:
        <input type="text" />
        <button type="submit">Submit</button>
      </label>
    </form>
    )
  }
}
ReactDOM.render(
  <NameForm />,
  document.getElementById('root'),
)

По умолчанию submit обновляет страницу. Чтобы это исправить, добавьте обработчик событий onSubmit в form. Затем назначьте this.handleSubmit на onSubmit. Затем добавьте свойство handleSubmit в тело класса (это общедоступное поле класса, которое мы обсуждали ранее) и назначьте ему стрелочную функцию, которая принимает event в качестве аргумента и возвращает event.preventDefault().

class NameForm extends React.Component {
  handleSubmit = event => {
    event.preventDefault()
  }
  render() {
    return (
    <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input type="text" />
        <button type="submit">Submit</button>
      </label>
    </form>
    )
  }
}

Теперь страница больше не обновляется при нажатии кнопки отправки.

Получение входного значения

Есть три способа получить входное значение.

  1. Свойство целевого события

Мы можем использовать event.target для возврата элемента, вызвавшего событие. Назначив event.target свойству объекта и записав его в консоль, мы сможем увидеть все свойства form.

Наш код выглядит так:

handleSubmit = event => {
    event.preventDefault()
    console.log({target: event.target})
  }

И мы можем найти в консоли значение ввода.

Присвоение event.target свойству в литерале объекта и его регистрация в React приведет к регистрации данных в консоли в формате стиля JSON, аналогичном JSON.stringify или console.dir(...).

В консоли мы нажимаем {target: form}, затем target:form, затем 0:input и, наконец, значение (...) под value, чтобы увидеть строку "Richard" или что-то еще, представленное в форме.

Зная это, мы могли бы получить значение с event.target[0].value.

2. Второй способ — добавить реквизит name к input.

Вот так: <input type="text" name="username"/>

Затем мы можем найти value ввода в консоли.

Нажмите на {target: form}, затем на target: form, затем на elements, username и, наконец, на значение (...) под value.

Мы могли бы получить ввод, аналогичный номеру 2, с помощью event.target.elements.username.value.

Записываем это в консоль:

console.log({target: event.target})
    console.log(event.target[0].value)
    console.log(event.target.elements.username.value)

И отправка Richard покажет это:

3. Последний способ — с реквизитом React ref.

Добавляем ref к input следующим образом:

<input type="text" name="username" ref={node => (this.inputNode = node)}/>

Можно записать значение в консоль следующим образом:

console.log(this.inputNode.value)

Хорошей практикой является не назначать стрелочные функции ссылкам, поскольку это пересоздает функцию при каждом повторном рендеринге и по другим причинам. Мы могли бы переписать код так:

setRef = node => {
    this.inputNode = node
  }
  render() {
    return (
    <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input type="text" name="username" ref={this.setRef}/>
        <button type="submit">Submit</button>
      </label>
    </form>

TL;DR

Есть три способа получить ввод из формы React.

  1. С целевым свойством события.
  2. С опорой name.
  3. С refs.

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

Создавайте динамические формы с помощью React

В этом разделе будет обсуждаться, как использовать реквизит onChange для ввода для динамической и пользовательской проверки формы, когда пользователь вносит изменения во ввод.

Ниже у нас есть форма, которая отображает метку Name, кнопку ввода и кнопку отправки. После нажатия кнопки отправки может появиться одно из двух сообщений об ошибке. Первый — если введено менее трех символов, а второй — если ввод не содержит символа «s». Если ошибки нет, мы успешно предупреждаем пользователя.

Этот опыт несколько неудобен для пользователя; было бы лучше, если бы сообщения об ошибках отображались по мере того, как пользователь печатал, а кнопка отправки была доступна только в том случае, если ввод был приемлемым. Давайте попробуем это закодировать.

Во-первых, давайте рассмотрим код в текущей статической форме. Это выглядит так:

class NameForm extends React.Component {
  handleSubmit = event => {
    event.preventDefault()
    const value = 
      event.target.elements.username.value
    const error = this.props.getErrorMessage(
      value,
    )
    if (error) {
      alert(`error: ${error}`)
    } else {
      alert(`success: ${value}`)
    }
  }
render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" name="username" />
        </label>
        <button type="submit">Submit</button>
      </form>
    )
  }
}
ReactDOM.render(
  <NameForm
    getErrorMessage={value => {
      if (value.length < 3) {
        return `Value must be at least 3 characters, but is only 2`
      }
      if (!value.includes('s')) {
        return `Value does not include "s" but it should!`
      }
      return null
    }}
  />,
  document.getElementById('root'),
)

Этот код отображает форму с обработчиком при нажатии кнопки отправки. Обработчик предотвращает поведение отправки по умолчанию, получает значение ввода, получает сообщение об ошибке из реквизита getErrorMessage в компоненте NameForm и либо предупреждает об ошибке, либо об успешном вводе значения.

Проверка ввода выполняется реквизитом getErrorMessage компонента NameForm. Это делается путем назначения функции стрелки, которая принимает входное значение в качестве аргумента и проверяет ввод с помощью операторов if.

Создание условной кнопки отправки

Мы должны сначала ввести состояние, чтобы сделать его динамическим. Добавьте состояние после начала тела класса следующим образом:

state = {error: null}

Добавьте свойство onChange во входные данные и назначьте ему this.handleChange следующим образом:

<input type="text" onChange={this.handleChange} name="username" />

Метод handleChange получает значение ввода и устанавливает свойство состояния error с реквизитом getErrorMessage. Код выглядит следующим образом:

handleChange = (event) => {
      const {value} = event.target
      this.setState({
        error: this.props.getErrorMessage(value)
      })
    }

Получите нашу ошибку в состоянии в начале метода рендеринга следующим образом:

const {error} = this.state

Отключите кнопку по умолчанию, назначив ей логическую функцию с error в качестве аргумента:

<button disabled={Boolean(error)} type="submit">Submit</button>

Теперь отправка неактивна, если нет ошибки.

Обратите внимание, что кнопка отправки включена (не выделена серым цветом) по умолчанию. Это потому, что код еще не проверил на наличие ошибок.

Один из способов исправить это — после монтирования компонентов. Мы можем скопировать код setState из handleChange в componentDidMount(). Измените value на пустую строку, так как нет никаких значений, когда ввод пуст. Это выглядит так после handleChange в коде:

componentDidMount() {
    this.setState({
      error: this.props.getErrorMessage('')
    })
  }

Это приведет к тому, что кнопка отправки будет неактивна по умолчанию.

В качестве альтернативы мы могли бы не иметь этого кода и инициализировать наше состояние с указанным выше значением error следующим образом:

state = {error:this.props.getErrorMessage('')}

Это было бы лучше, так как меньше кода и мы избегаем повторного рендеринга с setState в componentDidMount().

Динамическое отображение сообщения об ошибке

Давайте сделаем так, чтобы сообщение об ошибке отображалось по мере ввода пользователем.

Все, что нужно, это строка кода после метки и перед кнопкой:

{error ? <div style={{color: 'red'}}>{error}</div> : null}

Мы отображаем ошибку красным цветом, если она существует; иначе мы ничего не делаем.

TL;DR

Ключевые шаги, чтобы сделать кнопку отправки серой и отобразить сообщения об ошибках:

  1. Используйте реквизит onChange на входе.
  2. Создайте обработчик для реквизита onChange, который обновляет состояние.
  3. Используйте троичное выражение для условного отображения сообщений об ошибках и функцию Boolean() для проверки ошибок, чтобы отключить кнопку отправки.