---
title: События в JavaScript и React
seo:
  description: >-
    Тема «События в JavaScript и React» для собеседования React Developer. Что
    такое распространение события (Event Propagation)? Что такое всплытие
    события (Event Bubbling)?
  title: События в JavaScript и React — React Developer
---

[Все темы React Developer](/prep/react-developer)

Подтемы:

- [События в JS](#q-14bee738d69b811b834efeb69a5163de)
- [Обработка событий](#q-14bee738d69b8132946cd54e3c0633e9)
- [Методы обработки событий](#q-14bee738d69b8147acaeec2be0e3828a)

## Что такое распространение события (Event Propagation)? [#q-14bee738d69b811b834efeb69a5163de]

<code>Event Propagation</code> — это механизм, определяющий порядок, в котором
события обрабатываются в DOM-дереве.

#### Основные фазы&#58;

{/* prettier-ignore */}
1. <strong>Погружение (Capturing)</strong>&#58;

    - Событие начинается с корневого элемента и проходит вниз до целевого элемента.

    - Пример&#58;

        ```javascript
        element.addEventListener('click', handler, true); // true - использовать фазу погружения
        ```

1. <strong>Целевой элемент (Target)</strong>&#58;

    - Событие достигает целевого элемента и обрабатывается.

1. <strong>Всплытие (Bubbling)</strong>&#58;

    - Событие поднимается обратно вверх по дереву от целевого элемента к корневому.

    - Пример&#58;

        ```javascript
        element.addEventListener('click', handler); // По умолчанию false - использовать фазу всплытия
        ```

:::note[Ссылки для изучения]

1. [Всплытие и погружение событий DOM](https://learn.javascript.ru/bubbling-and-capturing)
2. [Фазы распространения событий и capturing. Александр Ламков. Friendly Frontend, с 18:14](https://www.youtube.com/watch?v=nxwNhad4jtk&t=1094s)

:::

---

## <strong>Что такое всплытие события (</strong><code>Event Bubbling</code><strong>)?</strong> [#q-14bee738d69b81e3ac13c86f749a88a1]

<code>Event Bubbling</code> — это процесс, при котором событие, сначала
обработанное целевым элементом, поднимается вверх по DOM-дереву, вызывая
обработчики событий на каждом из родительских элементов.

#### Основные характеристики&#58;

{/* prettier-ignore */}
1. <strong>Порядок обработки</strong>&#58;

    - Событие сначала обрабатывается целевым элементом.

    - Затем поднимается (всплывает) к его родительским элементам и далее к корневому элементу.

1. <strong>Пример</strong>&#58;

    ```javascript
    document.getElementById("child").addEventListener("click", function() {
        console.log("Child clicked");
    });

    document.getElementById("parent").addEventListener("click", function() {
        console.log("Parent clicked");
    });

    // При клике на элемент с id "child" сначала будет выведено "Child clicked", затем "Parent clicked"
    ```

Всплытие события позволяет обработчикам событий на родительских элементах реагировать на события, которые произошли на их потомках, начиная с целевого элемента и поднимаясь вверх по DOM-дереву.

:::note[Ссылки для изучения]

1. [Всплытие и погружение событий DOM](https://learn.javascript.ru/bubbling-and-capturing)
2. [Всплытие событий JavaScript. Александр Ламков. Friendly Frontend, с 12:12](https://www.youtube.com/watch?v=nxwNhad4jtk&t=732s)

:::

---

## <strong>Что такое погружение события (</strong><code>Event Capturing</code><strong>)?</strong> [#q-14bee738d69b8163a5f8d2d570a6d56a]

<code>Event Capturing</code> — это фаза распространения события в DOM, при
которой событие проходит сверху вниз от корневого элемента к целевому элементу.

#### Основные характеристики&#58;

{/* prettier-ignore */}
1. <strong>Порядок обработки</strong>&#58;

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

1. <strong>Включение захвата</strong>&#58;

    - Для использования фазы погружения необходимо установить третий параметр в <code>true</code> при добавлении обработчика событий.

    - Пример&#58;

        ```javascript
        document.getElementById("parent").addEventListener("click", function() {
            console.log("Parent clicked");
        }, true);

        document.getElementById("child").addEventListener("click", function() {
            console.log("Child clicked");
        }, true);
        ```

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

:::note[Ссылки для изучения]

1. [Всплытие и погружение событий DOM](https://learn.javascript.ru/bubbling-and-capturing)
2. [Фазы распространения событий и capturing. Александр Ламков. Friendly Frontend, с 18:14](https://www.youtube.com/watch?v=nxwNhad4jtk&t=1094s)

:::

---

## Что такое event.target? [#q-14bee738d69b81358b16ea3aed4faa62]

<span id="q-14bee738d69b81e8aecae09a451f1f3e"></span>

`event.target` указывает на элемент, на котором событие возникло изначально. При всплытии обработчик может находиться на родителе, а `target` всё равно укажет на вложенный элемент, по которому кликнули.

```js
list.addEventListener("click", (event) => {
  console.log(event.target);
});
```

Не путайте его с `event.currentTarget`: тот указывает на элемент, чей обработчик сейчас выполняется. [Документация MDN](https://developer.mozilla.org/docs/Web/API/Event/target).

:::note[Ссылки для изучения]

1. [Event Propagation: фазы погружения и всплытия](https://habr.com/ru/articles/749376/)
2. [Целевой элемент события event.target. Александр Ламков. Friendly Frontend, с 13:43](https://www.youtube.com/watch?v=nxwNhad4jtk&t=823s)

:::

---

## Что такое event.currentTarget? [#q-14bee738d69b81278273cd17d70eaaeb]

<span id="q-14bee738d69b8123a442f29edc0687cc"></span>

`event.currentTarget` указывает на элемент, на котором зарегистрирован обработчик, выполняющийся сейчас. При всплытии он может отличаться от `event.target`, где событие возникло.

```js
list.addEventListener("click", (event) => {
  console.log(event.target); // элемент, по которому кликнули
  console.log(event.currentTarget); // list
});
```

Вне обработчика `currentTarget` обычно равен `null`. [Документация MDN](https://developer.mozilla.org/docs/Web/API/Event/currentTarget).

:::note[Ссылки для изучения]

1. [Event Propagation: фазы погружения и всплытия](https://habr.com/ru/articles/749376/)
2. [Элемент обработчика event.currentTarget. Александр Ламков. Friendly Frontend, с 14:27](https://www.youtube.com/watch?v=nxwNhad4jtk&t=867s)

:::

---

## <strong>Как обрабатывать события в React?</strong> [#q-14bee738d69b8132946cd54e3c0633e9]

В React обработка событий происходит с использованием синтаксиса, аналогичного обработке событий в нативном JavaScript, но с некоторыми отличиями. Вот как обрабатывать события в React&#58;

1. <strong>Создание метода обработки события&#58;</strong> Создайте метод внутри
   компонента, который будет выполняться при возникновении события. Название
   метода обычно начинается с префикса "handle", за которым следует имя события
   или описательное имя.

1. <strong>Привязка метода к элементу&#58;</strong> Привяжите созданный метод к
   элементу, который будет генерировать событие. Это делается с помощью JSX,
   указав метод как значение атрибута события.

1. <strong>Использование аргументов&#58;</strong> Внутри метода обработки
   события вы можете получить доступ к объекту события и использовать его
   свойства, такие как <code>target</code>, чтобы получить информацию о событии.

Пример обработки клика&#58;

```jsx
import React, { Component } from "react";

class Button extends Component {
  handleClick = () => {
    console.log("Кнопка была нажата");
  };

  render() {
    return <button onClick={this.handleClick}>Нажми меня</button>;
  }
}

export default Button;
```

В этом примере метод <code>handleClick</code> вызывается при клике на кнопку, выводя сообщение в консоль.

Важно заметить, что при передаче метода обработки события в качестве атрибута JSX, не следует вызывать его с помощью круглых скобок (например, не пишите <code>onClick&#61;&#123;this&#46;handleClick&#40;&#41;&#125;</code>), так как это вызовет выполнение метода сразу при рендеринге.

:::note[Ссылки для изучения]

1. [Обработчики событий и распространение в React](https://reactdev.ru/learn/responding-to-events/)
   :::

---

## <strong>Что такое синтетические события (</strong><code>synthetic events</code><strong>) в React?</strong> [#q-14bee738d69b8191b77dd6c0838f528a]

В React, "синтетические события" (<code>synthetic events</code>) - это система обработки событий, которая предоставляет кросс-браузерную и кросс-платформенную абстракцию над нативными событиями браузера. Они создаются и управляются React и обеспечивают более единообразное поведение обработки событий в различных браузерах.

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

Пример использования синтетических событий&#58;

```jsx
import React from "react";

class Button extends React.Component {
  handleClick = (event) => {
    event.preventDefault();
    console.log("Button clicked!");
  };

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}
```

В этом примере, <code>event</code> является синтетическим событием, передаваемым в обработчик <code>handleClick</code>. Вы можете вызывать методы такие как <code>preventDefault&#40;&#41;</code>, <code>stopPropagation&#40;&#41;</code>, и другие, а также получать информацию о событии (например, <code>event&#46;target</code>, <code>event&#46;clientX</code>, и др.).

Синтетические события нормализуют интерфейс событий разных браузеров. В React DOM начиная с React 17 пулинг событий отключён, поэтому event.persist() для сохранения события не нужен.

:::note[Ссылки для изучения]

1. [Объект события React и его свойства](https://reactdev.ru/reference/react-dom/components/common/)
   :::

---

## <strong>Как реализовать</strong> <code>drag&#45;and&#45;drop</code> <strong>функциональность в React-приложении?</strong> [#q-14bee738d69b811897bdde84a40299be]

Реализация функциональности перетаскивания (<code>drag&#45;and&#45;drop</code>) в React-приложении может быть достигнута с использованием стандартных событий мыши и состояния компонентов React. Вот базовый подход к созданию такой функциональности&#58;

1. <strong>
     Создание компонентов для перетаскиваемых и целевых элементов&#58;
   </strong>
    Сначала создайте компоненты для элементов, которые вы хотите перемещать
   (перетаскиваемые элементы) и элементов, на которые вы хотите перетащить
   (целевые области).

1. <strong>Управление состоянием&#58;</strong> Добавьте состояние в компоненты,
   чтобы отслеживать, перетаскивается ли в данный момент элемент или нет.
   Например, вы можете использовать <code>useState</code> для этого.

1. <strong>Обработка событий&#58;</strong> В компонентах перетаскиваемых
   элементов, добавьте обработчики событий <code>onDragStart</code>, 
   <code>onDrag</code>, и <code>onDragEnd</code>&#58;

   ```html
   <div draggable onDragStart="{(e)" ="">
     handleDragStart(e, item)} onDrag={(e) => handleDrag(e)} onDragEnd={(e) =>
     handleDragEnd(e)} > {/* Содержимое перетаскиваемого элемента */}
   </div>
   ```

1. <strong>Реализация функций обработчиков&#58;</strong> Создайте функции
   обработчики для событий перетаскивания. В них вы будете обновлять состояние
   компонентов и манипулировать данными о перетаскиваемом элементе.

1. <strong>Определение областей для перетаскивания&#58;</strong> В целевых
   компонентах определите зоны, на которые можно бросить перетаскиваемый
   элемент. Добавьте обработчики событий <code>onDragOver</code> и 
   <code>onDrop</code>&#58;

   ```html
   <div onDragOver="{(e)" ="">
     handleDragOver(e)} onDrop={(e) => handleDrop(e, target)} > {/* Содержимое
     целевой области */}
   </div>
   ```

1. <strong>Реализация обработчиков для областей перетаскивания&#58;</strong>
    Аналогично создайте функции обработчики для событий <code>onDragOver</code>
    и <code>onDrop</code>, где вы будете предотвращать стандартное поведение
   браузера и обновлять состояние компонентов в соответствии с действиями
   пользователя.

1. <strong>Обновление состояния&#58;</strong> В функциях обработчиках обновляйте
   состояние компонентов так, чтобы отражать текущее состояние перетаскивания.

1. <strong>Рендеринг компонентов&#58;</strong> Не забудьте рендерить ваши
   компоненты в компоненте верхнего уровня, чтобы создать интерфейс
   перетаскивания.

Приведенный выше подход представляет базовую концепцию реализации <code>drag&#45;and&#45;drop</code> в React. В более сложных случаях, например, при необходимости поддержки перетаскивания между разными компонентами или списками, возможно потребуется использовать дополнительные библиотеки или углубиться в более сложные паттерны.

:::note[Ссылки для изучения]

1. [Браузерный HTML Drag and Drop API: dataTransfer и drop](https://developer.mozilla.org/ru/docs/Web/API/HTML_Drag_and_Drop_API)
1. [DragEvent и обработчики onDragStart, onDragOver, onDrop в React](https://reactdev.ru/reference/react-dom/components/common/)
   :::

---

## <strong>Как реализовать перетаскивание (</strong><code>drag&#45;and&#45;drop</code><strong>) элементов в React-приложении?</strong> [#q-14bee738d69b814d8addcfe9b25b7340]

Для реализации перетаскивания элементов в React-приложении вы можете использовать нативные события браузера в сочетании с состоянием компонентов React. Вот базовые шаги, как это можно сделать&#58;

{/* prettier-ignore */}
1. <strong>Создание компонентов&#58;</strong>

    - Создайте компоненты, которые вы планируете перемещать.

    - Определите обработчики событий для начала и завершения перетаскивания.

1. <strong>Управление состоянием&#58;</strong>

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

1. <strong>Добавление обработчиков событий&#58;</strong>

    - Добавьте обработчик события <code>onDragStart</code> для элемента, который будет перетаскиваться. В этом обработчике установите данные о перетаскиваемом элементе в состояние, используя функцию <code>setData</code> и <code>event&#46;dataTransfer</code>.

    - Добавьте обработчики <code>onDragOver</code> и <code>onDrop</code> для контейнера, куда вы собираетесь перемещать элементы. В обработчике <code>onDragOver</code> предотвратите действие по умолчанию, чтобы разрешить перетаскивание, и в обработчике <code>onDrop</code> обработайте перетаскивание элемента.

Пример&#58;

```jsx
import React, { useState } from "react";

function DraggableElement({ text }) {
  const handleDragStart = (event) => {
    event.dataTransfer.setData("text/plain", text);
  };

  return (
    <div draggable onDragStart={handleDragStart} className="draggable-element">
      {text}
    </div>
  );
}

function DroppableArea() {
  const [droppedItems, setDroppedItems] = useState([]);

  const handleDragOver = (event) => {
    event.preventDefault();
  };

  const handleDrop = (event) => {
    event.preventDefault();
    const droppedText = event.dataTransfer.getData("text/plain");
    setDroppedItems([...droppedItems, droppedText]);
  };

  return (
    <div
      className="droppable-area"
      onDragOver={handleDragOver}
      onDrop={handleDrop}
    >
      {droppedItems.map((item, index) => (
        <div key={index}>{item}</div>
      ))}
    </div>
  );
}

function App() {
  return (
    <div className="app">
      <DraggableElement text="Перетащи меня!" />
      <DroppableArea />
    </div>
  );
}

export default App;
```

:::note[Ссылки для изучения]

1. [Браузерный HTML Drag and Drop API: dataTransfer и drop](https://developer.mozilla.org/ru/docs/Web/API/HTML_Drag_and_Drop_API)
1. [DragEvent и обработчики onDragStart, onDragOver, onDrop в React](https://reactdev.ru/reference/react-dom/components/common/)
   :::

---

## <strong>В чем разница между методами</strong> <code>event&#46;preventDefault&#40;&#41;</code> <strong>и</strong> <code>event&#46;stopPropagation&#40;&#41;</code><strong>?</strong> [#q-14bee738d69b8147acaeec2be0e3828a]

Разница между <code>event&#46;preventDefault&#40;&#41;</code> и <code>event&#46;stopPropagation&#40;&#41;</code>&#58;

{/* prettier-ignore */}
1. <code>event&#46;preventDefault&#40;&#41;</code>&#58;

    - <strong>Назначение</strong>&#58; Предотвращает стандартное поведение браузера для события.

    - <strong>Пример</strong>&#58;

        ```javascript
        document.getElementById("myLink").addEventListener("click", function(event) {
            event.preventDefault(); // Отменяет переход по ссылке
        });
        ```

1. <code>event&#46;stopPropagation&#40;&#41;</code>&#58;

    - <strong>Назначение</strong>&#58; Останавливает дальнейшее распространение события (всплытие или погружение).

    - <strong>Пример</strong>&#58;

        ```javascript
        document.getElementById("child").addEventListener("click", function(event) {
            event.stopPropagation(); // Останавливает всплытие события
        });
        ```

#### Итог&#58;

- <code>event&#46;preventDefault&#40;&#41;</code>&#58; Отменяет стандартное
  поведение события.

- <code>event&#46;stopPropagation&#40;&#41;</code>&#58; Останавливает
  распространение события по DOM-дереву.

:::note[Ссылки для изучения]

1. [Действия браузера по умолчанию и preventDefault](https://learn.javascript.ru/default-browser-action)
1. [Распространение событий и stopPropagation](https://learn.javascript.ru/bubbling-and-capturing)
   :::

---

## <strong>Как узнать об использовании метода</strong> <code>event&#46;preventDefault&#40;&#41;</code><strong>?</strong> [#q-14bee738d69b818f9fc4d1fc273fdbd8]

event.defaultPrevented показывает, была ли успешно отменена стандартная обработка события. Вызов preventDefault() не меняет это свойство, если событие неотменяемое или обработчик passive.

#### Пример использования&#58;

```javascript
document.getElementById("myLink").addEventListener("click", function (event) {
  event.preventDefault();
  console.log(event.defaultPrevented); // true
});
```

event.defaultPrevented показывает, была ли успешно отменена стандартная обработка события. Вызов preventDefault() не меняет это свойство, если событие неотменяемое или обработчик passive.

:::note[Ссылки для изучения]

1. [event.defaultPrevented: проверка отмены действия браузера](https://learn.javascript.ru/default-browser-action)
   :::
