#5 React - как работать с формами

poster
В этом уроке мы разберем что такое react forms и как с ними работать. Научимся отправлять форму и сохранять значение в стейте.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

Всем привет. В этом уроке мы разберем как работать в реакте с формами.

Давайте попробуем.

Создадим компонент с формой регистрации. Создадим файл RegistrationForm.js

Добавим туда пустую заготовку под компонент

import React, { Component } from 'react';

class RegistrationForm extends Component {
  render() {
    return (
      <div>Form</div>
    );
  }
}

export default RegistrationForm;

И импортируем ее в App.js и уберем ненужный код с прошлого урока.

import RegistrationForm from './RegistrationForm';

Как мы видим, в браузере вывелась наша компонента.

Давайте теперь добавим форму и submit метод.

<form onSubmit={this.handleSubmit}>
</form>

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

constructor(props) {
  super(props);
  this.state = {
    email: ''
  };
}

Создадим конструктор, вызываем super и задаем дефолтное значение для email.

Добавим input в нашу форму.

<form onSubmit={this.handleSubmit}>
  <input
    type="text"
    placeholder="E-mail"
    value={this.state.email}
    onChange={this.handleEmailChange}
  />
</form>

Как значение зададим this.state.email. Также нам нужно задать onChange функцию. Она будет стрелять каждый раз, когда мы изменяем email.

И добавим метод handleSubmit и handleEmailChange

handleSubmit() {
  console.log('form is submitted');
}

handleEmailChange() {
  console.log('handleEmailChange', this);
}

Если мы законсолим this в функции handleEmailChange, то увидим в браузере, что он undefined, так же, как у нас было в уроке про локальный стейт. В тот раз мы писали bind прямо в методе .bind(this). Другой вариант это написать bind в конструкторе.

this.handleEmailChange = this.handleEmailChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);

Это просто переприсваивает функции с правильным this.

Теперь в браузере мы видим правильный this.

Давайте теперь когда стреляет функция handleEmailChange сетить значение в стейт.

handleEmailChange(event) {
  console.log('handleEmailChange', this);
  this.setState({email: event.target.value});
}

Теперь каждый раз при изменении инпута у нас будет менятся значение в локальном стейте.

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

Как вы видите, у нас сразу же в инпуте отображаются данные. Если мы уберем строчку setState, то мы будем что-то печатать и у нас ничего не отображается, поскольку значение this.state.email не изменилось. Как только мы вызываем setState, у нас отображается значение с локального стейта.

Давайте изменим немного сообщение в handleSubmit.

console.log('form submitted and email value is', this.state.email);

Как мы видим в браузере, если мы напишем что-то в input и нажмем enter, console.log у нас выводится, но страница перегружается так как это обычная форма. Для того, чтобы это пофиксить давайте добавим event.preventDefault().

handleSubmit(event) {
  event.preventDefault();
  console.log('form submitted and email value is', this.state.email);
}

Теперь если мы будем что-то писать в инпуте и нажмем enter, то у нас страница не перезагружается и в консоли мы видим надпись.

Ну и напоследок давайте добавим кнопку для сабмита формы

<button>Save</button>

Так как у button, по умолчанию тип submit, и наша форма отправляется и мы попадаем в функцию handleSubmit.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Moe Green
10 месяцев назад
чтобы не копировать компоненты, можно создать сниппеты под VSC. например, так - https://www.youtube.com/watch?v=Swwhj3Nlh-c
Rustam Apaev
1год назад назад
Почему-то такой метод в консоль выводит стейт с опозданием на 1 символ. Ели я ввел "abc" , в консоли будет "ab" handleEmailChange(event) { this.setState( {email: event.target.value}); console.log('Email was changed', this.state.email); } А если вывести в консоли event.target.value, то не будет никаких опозданий... Хотя по логике эти величины одинаковые должны быть... Такой же результат будет если вывод консоли разместить раньше обновления стейта.
monsterlessons
1год назад назад
Такое поведение абсолютно правильно, потому что setState асинхронный. Для того, чтобы дождаться его выполнения используйте callback. this.setState({email: event.target.value}, () => console.log('Email was changed', this.state.email))
Dmitry Pocheketa
1год назад назад
Для <button> стоит добавить type=submit. Он по дефолту в хроме, но в остальных браузерах может отличатся. В Firefox по дефолту type=button, если я не ошибаюсь.
monsterlessons
1год назад назад
Wow я даже не знал. Думал везде type=submit. Always specify the type attribute for the button. The default type for Internet Explorer is "button", while in other browsers (and in the W3C specification) it is "submit". Так что везде нормально кроме IE. В IE 11 уже работает правильно, так что думаю в Edge тоже. Согласен надо везде ставить type.
Karen Kostanyan
2 лет назад
Как здесь работает submit а где action? или просто url я напишу handleSubmit? И как будет работать мой server api простой ajax или есть поинтереснее ?
monsterlessons
2 лет назад
Вы имеете ввиду Redux? Екшен можно диспатчить прямо в handleSubmit. И внутри этого екшена, если он асинхронный вы можете делать запросы к API. Про асинхронные екшены вы можете посмотреть тут https://monsterlessons.com/project/lessons/reduxjs-asinhronnye-eksheny-s-pomoshyu-redux-thunk
Karen Kostanyan
2 лет назад
А имеет ли смысл на реакте писать не асинхронный запрос?
monsterlessons
2 лет назад
Зависит от задачи. Если вам не нужно обращаться к API, а только обновлять данные на клиенте, то синхронных екшенов достаточно.
Karen Kostanyan
2 лет назад
ну сейчас все проекты через API пишут ... ))))
monsterlessons
2 лет назад
Я не говорил, что не пишут. Я говорил, что если при отправке формы нужно только обновить данные на клиенте не дергая апи, то достаточно синхронных екшенов. Например у вас уже загруженный список и вы его хотите на клиенте отфильтровать. Тогда достаточно синхронного екшена.