React handling form submission

Javascript урок 17 события

Объект события и метод preventDefault

Событие — это какое-то действие, произошедшее на странице. Например, клик, нажатие кнопки, движение мыши, отправка формы и так далее. Когда срабатывает событие, браузер создаёт объект события Event. Этот объект содержит всю информацию о событии. У него есть свои свойства и методы, с помощью которых можно эту информацию получить и использовать. Один из методов как раз позволяет отменить действие браузера по умолчанию — .

 можно передать в функцию-обработчик события и в ней указать инструкции, которые должны быть выполнены, когда оно сработает. При передаче объекта события в обработчик обычно используется сокращённое написание — .

Пример: когда ссылка — не ссылка

Ранее мы уже говорили о попапе, который должен появляться при клике на ссылку — давайте разберём этот кейс на практике. Так будет выглядеть разметка в упрощённом виде:

Мы хотим при клике на ссылку  добавлять элементу с классом  класс . Он сделает попап видимым, поменяв значение свойства  с  на . Напишем логику добавления этого класса с помощью JavaScript:

Если мы уберём строку , вместо попапа откроется отдельная страница , адрес которой прописан в атрибуте  у ссылки. Такая страница нужна, потому что мы хотим, чтобы вся функциональность сайта была доступна, если скрипт по какой-то причине не будет загружен. Именно поэтому мы изначально реализовали кнопку с помощью тега , а не . Но у нас с JavaScript всё в порядке, поэтому вместо отдельной страницы мы открыли попап, отменив действие браузера по умолчанию.

Пример: проверка формы перед отправкой

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

При нажатии на кнопку «Готово» сработает событие отправки формы , и форма отправится вне зависимости от корректности введённого значения, поэтому мы должны перехватить отправку.

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

18.3 Designing documents for user agents that don’t support scripting

The following sections discuss how authors may create documents that work
for user agents that don’t support scripting.

18.3.1 The NOSCRIPT element

<!ELEMENT  - - ()+
  -- alternate content container for non script-based rendering -->
<!ATTLIST NOSCRIPT
                                -- , ,  --
  >

Start tag: required, End tag:
required

  • The user agent is configured not to evaluate scripts.
  • The user agent doesn’t support a scripting language invoked by a
    element earlier in the document.

User agents that do not support client-side scripts must render this
element’s contents.

In the following example, a user agent that executes the
will include some dynamically created data in the document. If the user agent
doesn’t support scripts, the user may still retrieve the data through a
link.

<SCRIPT type="text/tcl">
 ...some Tcl script to insert data...
</SCRIPT>
<NOSCRIPT>
 <P>Access the <A href="http://someplace.com/data">data.</A>
</NOSCRIPT>

18.3.2 Hiding script data from user
agents

User agents that don’t recognize the element will likely render
that element’s contents as text. Some scripting engines, including those for
languages JavaScript, VBScript, and Tcl allow the script statements to be
enclosed in an SGML comment. User agents that don’t recognize the
element will thus ignore the comment while smart scripting engines will
understand that the script in comments should be executed.

Another solution to the problem is to keep scripts in external documents and
refer to them with the attribute.

Commenting scripts in JavaScript

The JavaScript engine allows the string «<!—» to occur at the start of a
SCRIPT element, and ignores further characters until the end of the line.
JavaScript interprets «//» as starting a comment extending to the end of the
current line. This is needed to hide the string «—>» from the JavaScript
parser.

<SCRIPT type="text/javascript">
<!--  to hide script contents from old browsers
  function square(i) {
    document.write("The call passed ", i ," to the function.","<BR>")
    return i * i
  }
  document.write("The function returned ",square(5),".")
// end hiding contents from old browsers  -->
</SCRIPT>

Commenting scripts in VBScript

In VBScript, a single quote character causes the rest of the current line to
be treated as a comment. It can therefore be used to hide the string «—>»
from VBScript, for instance:

   <SCRIPT type="text/vbscript">
     <!--
       Sub foo()
        ...
       End Sub
     ' -->
    </SCRIPT>

Commenting scripts in TCL

In Tcl, the «#» character comments out the rest of the line:

<SCRIPT type="text/tcl">
<!--  to hide script contents from old browsers
  proc square {i} {
    document write "The call passed $i to the function.<BR>"
    return 
  }
  document write "The function returned ."
# end hiding contents from old browsers  -->
</SCRIPT>

Note. Some browsers close comments on the first «>»
character, so to hide script content from such browsers, you can transpose
operands for relational and shift operators (e.g., use «y < x» rather than
«x > y») or use scripting language-dependent escapes for «>».

previous  
next     elements   attributes  
index

Get Form Control Elements By Their Names

We can access the form controls by using the value in the element’s attribute, for example, in the following way:

const handleSubmit = (event) => {
    event.preventDefault();

    const emailInput = event.target.email; // accessing directly
    const ageInput = event.target.elements.age; // accessing via `form.elements`

    console.log(emailInput.value); // output: 'f'
    console.log(ageInput.value); // output: '18'
};

From the example above we can see that:

  • refers to the element;
  • Names of form control elements must match the value specified in their respective attributes;
  • Form controls can be accessed by their name in the following ways:
    • Directly (e.g. ), or;
    • By using the property (e.g. ), or;
    • By using the method (e.g. ).

The property returns an object, which allows us to access form controls in that form by using the element’s , which is similar to using the method. The difference between the two is the fact that the former would return if the element doesn’t exist, while the latter would return .

Работа с формами

Последнее обновление: 01.04.2022

Хотя в React мы можем использовать все стандартные элементы форм, которые есть в html, однако здесь эти элементы приобретают дополнительные возможности. Рассмотрим, как работать с формами в React.

Определим на веб-странице следующий код:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Формы в React</title>
</head>
<body>
    <div id="app"></div>
       
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
       
    <script type="text/babel">
    class UserForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {name: ""};
  
        this.onChange = this.onChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
      onChange(e) {
        var val = e.target.value;
        this.setState({name: val});
    }
  
      handleSubmit(e) {
        e.preventDefault();
        alert("Имя: " + this.state.name);
      }
  
      render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <p>
                    <label>Имя:</label><br />
                    <input type="text" value={this.state.name} onChange={this.onChange}/>
                </p>
                <input type="submit" value="Отправить" />
            </form>
        );
      }
    }
    ReactDOM.createRoot(
        document.getElementById("app")
    )
    .render(
        <UserForm />
    );
    </script>
</body>
</html>

Определенный здесь компонент UserForm представляет форму для ввода имени пользователя с возможностью условной отправки.

Чтобы контролировать введенные значения, в конструкторе устанавливается объект state:

this.state = {name: ""};

При определении поля ввода каждое поле связывается с определенным значением в state:

<input type="text" value={this.state.name} onChange={this.onChange} />

Так, источником значения для поля ввода имени является объект .

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

Суть каждого обработчика заключается в изменении значений в this.state:

onChange(e) {
	var val = e.target.value;
	this.setState({name: val});
}

С помощью получаем введенное значение. После обновления новое значение this.state.name отобразится в поле ввода.

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

НазадВперед

События мыши:

Событие Описание
onclick реагирует на клик мыши;
ondblclick реагирует на двойной клик;
oncontextmenu реагирует на клик правой кнопкой мыши;
onmouseover реагирует на наведение мыши (на дочерние элементы тоже);
onmouseenter реагирует на наведение мыши;
onmouseout реагирует на отведение мыши (на дочерние элементы тоже);
onmouseleave реагирует на отведение мыши;
onmousedown реагирует на зажатие кнопки мыши;
onmouseup реагирует на отпускание кнопки мыши;
onmousemove реагирует при движении указателя мыши над элементов;
onwheel реагирует при движении колёсика мыши над элементом;
altKey реагирует на нажатие кнопки мыши при нажатой клавиши ALT;
ctrlKey реагирует на нажатие кнопки мыши при нажатой клавиши CTRL;
shiftKey реагирует на нажатие кнопки мыши при нажатой клавиши SHIFT;
metaKey реагирует на нажатие кнопки мыши при нажатой клавиши META(◆,⌘);
button возвращает номер нажатой клавиши мыши (0,1,2);
buttons возвращает номер нажатой клавиши мыши (1,2,4,8,16);
which возвращает номер нажатой клавиши мыши (1,2,3);
clientX возвращает координату указателя мыши по оси X (относительно окна);
clientY возвращает координату указателя мыши по оси Y (относительно окна);
detail возвращает количество кликов по объекту;
relatedTarget возвращает родственный элемент;
screenX возвращает координату указателя мыши по оси X (относительно экрана);
screenY возвращает координату указателя мыши по оси Y (относительно экрана);
deltaX возвращает количество скроллов по оси X;
deltaY возвращает количество скроллов по оси Y;
deltaZ возвращает количество скроллов по оси Z;
deltaMode возвращает единицу измерения длины скролла;

Событие onsubmit

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

пример

В следующем примере показано, как использовать . Здесь мы вызываем функцию перед отправкой данных формы на веб-сервер. Если функция возвращает true, форма будет отправлена, в противном случае она не представит данные.

Попробуйте следующий пример.

<html>
   <head>
  
      <script type="text/javascript">
         <!--
            function validation() {
               all validation goes here
               .........
               return either true or false
            }
         //-->
      </script>
     
   </head>
   <body>
  
      <form method="POST" action="t.cgi" onsubmit="return validate()">
         .......
         <input type="submit" value="Submit" />
      </form>
     
   </body>
</html>

React Form by Example

A common example of a form in a web application these days is a login form. It allows the authentication and authorization of a user to access the application. In React, we would use a functional component to represent such form:

import*asReactfrom'react';

constLoginForm=()=>{

return(

<form>

<div>

<labelhtmlFor="email">Email</label>

<inputid="email"type="text"/>

</div>

<div>

<labelhtmlFor="password">Password</label>

<inputid="password"type="password"/>

</div>

<button>Submit</button>

</form>

);

};

export{LoginForm};

The form component displays two HTML input fields with each having an attached HTML label element. All elements are used within a HTML form element.

Continue Reading: React Elements vs Components

For accessibility reasons in a form, a HTML label element can use a attribute (React specific) which links to the HTML input element’s attribute. When clicking the form’s labels, the respective input fields should get focused.

Note that the form does not receive any props yet. Later it could receive props for its initial state which populate the form or a callback handler which gets executed when clicking the form’s submit button.

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

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

Мы можем объединить всё это вместе, сделав состояние React «единственным источником данных (истины)». Затем компонент React, который отрисовывает форму, также контролирует, что происходит в этой форме при последующем вводе данных пользователем. Элемент поля ввода формы, значение которого контролируется React подобным образом, называется «контролируемым компонентом».

Например, если мы хотим, чтобы предыдущий пример выводил на консоль имя при отправке формы, мы можем написать её как контролируемый компонент:

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

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

Тип события — onsubmit

onsubmit это событие, которое происходит при попытке отправить форму. Вы можете поместить свою форму проверки в отношении этого типа события.

Пример

В следующем примере показано, как использовать событие onsubmit. Здесь мы вызываем функцию validate() перед отправкой формы данных на веб-сервер. Если функция  validate() возвращает истину, форма будет отправлена, в противном случае она не будет предоставлять данные.

Попробуйте следующий пример.

<html>
   <head>
   
      <script type="text/javascript">
         <!--
            function validation() {
               вся проверка идет сюда
               .........
               возвращает либо true или false
            }
         //-->
      </script>
      
   </head>
   <body>
   
      <form method="POST" action="t.cgi" onsubmit="return validate()">
         .......
         <input type="submit" value="Submit" />
      </form>
      
   </body>
</html>

React Form Dirty

A form is dirty if one of its form fields has been changed by a user. When using forms, the dirty state helps with certain scenarios. For example, the submit button should only be enabled if a form field has changed:

constINITIAL_STATE={

email'',

password'',

};

constgetDirtyFields=(form)=>

Object.keys(form).reduce((acc, key)=>{



const isDirty = formkey!==INITIAL_STATEkey;

return{...acc,key isDirty };

},{});

constLoginForm=({ onLogin })=>{

constform, setForm=React.useState(INITIAL_STATE);

...

const dirtyFields =getDirtyFields(form);

const hasChanges =Object.values(dirtyFields).every(

(isDirty)=>!isDirty

);

return(

<formonSubmit={handleSubmit}>
      ...
<buttondisabled={hasChanges}type="submit">
        Submit
</button>

</form>

);

};

The previous code snippet shows an implementation of establishing a computed state which knows about each form field’s dirty state. However, this already shows the complexity of managing this dirty state yourself. Hence my recommendation of using a form library like React Hook Form.

Cookies

<FORM>
<INPUT TYPE=button VALUE="Показать Cookies"
onClick="window.alert(window.document.cookie);">
<FORM>
function asign()
{
document.cookie="n1=3";
window.alert(document.cookie);
}
...
<FORM>
<INPUT TYPE=button VALUE="Изменить n1" onClick="asign()">
<FORM>
function change_cookies()
{
a = new Array();
c = new Date();
a = document.cookie.split(';');
document.cookie=a+"; expires="+c.toGMTString()+";";
window.alert(document.cookie);
}
...
<FORM>
<INPUT TYPE=button VALUE="delete cookies" onClick="change_cookies()">
<FORM>
<script type="text/javascript">
var clickCount = ;
function documentClick(){
document.getElementById('clicked').value = ++clickCount;
}
document.onclick = documentClick;
<script>

. Однако в данном примере оператор ++ используется перед переменной. В первом примере clickCountclickCount единица добавляется к переменной clickCount перед чтением ее значения. Так как в этом примере переменной clickCount в начале присваивается значение 0, то единицу к ней необходимо добавлять до задания значения поля ввода, поэтому использована запись

<script type="text/javascript">
function showValue(obj){
alert('You Clicked On ' + obj.value);
}
<script>
<input type="radio" name="fruit" onclick="showValue(this);" value="Яблоко" >
Яблоко
<input type="radio" name="fruit" onclick="showValue(this);" value="Апельсин"
> Апельсин
<input type="radio" name="fruit" onclick="showValue(this);" value="Груша" >
Груша
<input type="radio" name="fruit" onclick="showValue(this);" value="Банан">
Банан
function myFunction(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10){
}
function myFunction(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10){
if(arg4){
}
if(arg5 && arg6 && arg7){
if(arg8){
}
}
if(arg9 || arg10){
}
}
function myFunction(){
for(var i=; i<arguments.length; i++){
alert(argumentsi.value);
}
}
<script type="text/javascript">
function multiply(){
var out=1;
for(var i=; i<arguments.length; i++){
out *= argumentsi;
}
return out;
}
function add(){
var out=;
for(var i=; i<arguments.length; i++){
out += argumentsi;
}
return out;
}
function doAction(action){
alert(action(1, 2, 3, 4, 5));
}
<script>
<button onclick="doAction(multiply)">Test Multiply<button>
<button onclick="doAction(add)" >Test Add<button>
function myFunction(){
function nestedFunction1(arg1, arg2, arg3){
alert(arg1+arg2+arg3);
}
var nestedFunction2 = function(arg1, arg2, arg3){
alert(arg1+arg2+arg3);
}
var nestedFunction3 = new Function('arg1, arg2, arg3',
'alert(arg1+arg2+arg3);');
}

События Form

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

Событие onfocus

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

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

Значение ключевого слова в обработчике события относится к элементу, на котором есть обработчик (то есть, куда в данный момент доставляется событие).

Событие onblur

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

Следующий пример покажет вам предупреждающее сообщение, когда элемент ввода текста теряет фокус.

Чтобы отвести фокус от элемента формы, сначала щелкните внутри него, затем нажмите клавишу табуляции на клавиатуре, наведите фокус на что-то другое или щелкните за его пределами.

Событие onchange

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

В следующем примере будет показано предупреждающее сообщение при изменении параметра в поле выбора.

Событие onsubmit

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

В следующем примере будет показано предупреждение при отправке формы на сервер.

React Form with onSubmit

When a user clicks the submit button of a form, we can use the HTML form element’s onSubmit attribute for attaching an event handler to it. In order to tell the form that the button should initiate the form’s event handler, the button has to have the submit type:

import*asReactfrom'react';

constLoginForm=()=>{

consthandleSubmit=(event)=>{

    event.preventDefault();

};

return(

<formonSubmit={handleSubmit}>

<div>

<labelhtmlFor="email">Email</label>

<inputid="email"type="text"/>

</div>

<div>

<labelhtmlFor="password">Password</label>

<inputid="password"type="password"/>

</div>

<buttontype="submit">Submit</button>

</form>

);

};

export{LoginForm};

For preventing the native browser behavior (which would perform a refresh on the browser), we can use the method on the form’s event.

Continue Reading: What is preventDefault in React

React Form with Validation

The most common culprit for using a form library is the validation of forms. While the following implementation seems rather straightforward, there are lots of moving parts which go into a sophisticated validation. So stay with me and learn how to perform such task yourself, but don’t hesitate to use a form library for it eventually:

constINITIAL_STATE={

email'',

password'',

};

constVALIDATION={

email

{

isValid(value)=>!!value,

message'Is required.',

},

{

isValid(value)=>\S+@\S+\.\S+.test(value),

message'Needs to be an email.',

},

,

password

{

isValid(value)=>!!value,

message'Is required.',

},

,

};

constgetErrorFields=(form)=>

Object.keys(form).reduce((acc, key)=>{

if(!VALIDATIONkey)return acc;

const errorsPerField =VALIDATIONkey





.map((validation)=>({

isValid validation.isValid(formkey),

message validation.message,

}))



.filter((errorPerField)=>!errorPerField.isValid);

return{...acc,key errorsPerField };

},{});

constLoginForm=({ onLogin })=>{

constform, setForm=React.useState(INITIAL_STATE);

...

const errorFields =getErrorFields(form);

console.log(errorFields);

return(...);

};

By having all the errors per form field as computed properties, we can perform tasks like preventing a user from submitting the form if there is a validation error:

constLoginForm=({ onLogin })=>{

...

consthandleSubmit=(event)=>{

    event.preventDefault();

const hasErrors =Object.values(errorFields).flat().length>;

if(hasErrors)return;



};

return(...);

};

What may be almost more important is showing the user feedback about form errors. Because we have all the errors there, we can display them conditionally as hints in JSX:

constLoginForm=()=>{

...

const errorFields =getErrorFields(form);

return(

<formonSubmit={handleSubmit}>

<div>

<labelhtmlFor="email">Email</label>

<input

id="email"

type="text"

value={form.email}

onChange={handleChange}

/>

{errorFields.email?.length ?(

<spanstyle={{color'red'}}>

{errorFields.email.message}

</span>

)null}

</div>

<div>

<labelhtmlFor="password">Password</label>

<input

id="password"

type="password"

value={form.password}

onChange={handleChange}

/>

{errorFields.password?.length ?(

<spanstyle={{color'red'}}>

{errorFields.password.message}

</span>

)null}

</div>

<buttontype="submit">Submit</button>

</form>

);

};

Learning more and more about form handling in React reveals how complex certain topics become over time. We only touched the surface here. It’s great to learn how everything works under the hood, hence this tutorial about forms in React, however, eventually you should opt-in a form library like React Hook Form.

Form Library: React Hook Form

My go-to form library these days in React Hook Form. One could say that it is a headless form library, because it doesn’t come with any form components, but just with custom React Hooks which allow you to access form state, dirty state, and validation state. But there is much more: Integration in third-party UI libraries, performant re-renders, form watchers, and usage of third-party validation libraries like Yup and Zod.

Continue Reading: Popular React Libraries

React uses synthetic events to handle events from button, input and form elements. A synthetic event is a shell around the native DOM event with additional information for React. Sometimes you have to…

Неотменяемые события

Не для всех событий можно отменить действие по умолчанию. Например, событие прокручивания страницы  проигнорирует попытки отменить его. Чтобы узнать, можно отменить действие по умолчанию или нет, нужно обратиться к свойству  объекта . Оно будет равно , если событие можно отменить, и  — в обратном случае.

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

React Form Template

The previous examples have given you many copy and paste templates which get you started with a form in React. However, so far we have only used two HTML input elements in a React form. There are many other form fields that you could add as reusable component:

  • React Checkbox
  • React Radio Button
  • React Dropdown

You have seen the basic usage of forms in React. Next we will walk through some more advanced form concepts which should illustrate the complexity of forms. While you walk through them, you learn how to implement these advanced concepts, however, note that eventually a dedicated form library will take care of these implementations.

Submit a React Form

You have already seen how to create a submit button for a form in React. So far, we only triggered this button and used its attached event handler, but we didn’t send any form data yet. Usually a form component receives a callback handler from a parent component which uses the form data:

constLoginForm=({ onLogin })=>{

constform, setForm=React.useState({

email'',

password'',

});

consthandleChange=(event)=>{

setForm({

...form,

event.target.id event.target.value,

});

};

consthandleSubmit=(event)=>{

    event.preventDefault();

onLogin(form);

};

return(...);

};

The example shows how form state is passed to the callback handler as form data. Therefore, once a user clicks the submit button, the parent component will receive the form data and perform a task with it (e.g. post form data to a backend).

Понравилась статья? Поделиться с друзьями:
Setup Pro
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: