---
title: Асинхронность
seo:
  description: >-
    Тема «Асинхронность» для собеседования React Developer. Как выполнить
    HTTP-запросы в React? Как обновить состояние компонента после выполнения
    асинхронной операции?
  title: Асинхронность — React Developer
questionDates:
  q-transfer-0440: '2026-10-01'
  q-transfer-0441: '2026-10-01'
  q-transfer-0442: '2026-10-01'
  q-transfer-0461: '2026-10-01'
---

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

<span
  id="q-14bee738d69b81ad824af0e20ed23bc7"
  data-question-redirect="/prep/react-developer/marshrutizaciya#q-14bee738d69b81d09077d127aec67faa"
></span>

## <strong>Как выполнить HTTP-запросы в React?</strong> [#q-14bee738d69b81608a3ec697829b6f91]

Для выполнения HTTP-запросов в React можно использовать стандартные методы, такие как <code>fetch</code> или библиотеки, такие как <code>axios</code>.

#### Пример с использованием <code>fetch</code>&#58;

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

const MyComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch("https://api.example.com/data")
      .then((response) => response.json())
      .then((data) => setData(data))
      .catch((error) => console.error("Error fetching data:", error));
  }, []);

  return (
    <div>
      {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : "Loading..."}
    </div>
  );
};

export default MyComponent;
```

#### Пример с использованием <code>axios</code>&#58;

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

const MyComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    axios
      .get("https://api.example.com/data")
      .then((response) => setData(response.data))
      .catch((error) => console.error("Error fetching data:", error));
  }, []);

  return (
    <div>
      {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : "Loading..."}
    </div>
  );
};

export default MyComponent;
```

Запрос при появлении компонента можно выполнить в useEffect. Проверяйте response.ok у fetch, храните состояние ошибки и отменяйте запрос либо игнорируйте устаревший ответ в cleanup. Запрос по действию пользователя запускайте из обработчика события. Кеширование и повторную загрузку удобнее поручить библиотеке или загрузчику маршрута.

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

1. [Получение данных, async/await и гонки ответов в useEffect](https://ru.react.dev/reference/react/useEffect)
2. [HTTP-запрос в React через Axios. Ulbi TV, с 1:36:20](https://www.youtube.com/watch?v=GNrdg3PzpJQ&t=5780s)

:::

---

## Как обновить состояние React-компонента после асинхронной операции? [#q-14bee738d69b8161ae75e4f5ecb0306c]

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

После завершения операции вызовите setter из `useState`. Если запрос запускается из эффекта, не делайте сам callback `useEffect` асинхронным: объявите async-функцию внутри эффекта и вызовите её. Храните отдельно данные, состояние загрузки и ошибку.

```jsx
useEffect(() => {
  const controller = new AbortController();
  let ignore = false;
  setLoading(true);
  setError(null);

  const load = async () => {
    try {
      const response = await fetch(url, { signal: controller.signal });
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const result = await response.json();
      if (!ignore) setData(result);
    } catch (error) {
      if (!ignore && error.name !== "AbortError") setError(error);
    } finally {
      if (!ignore) setLoading(false);
    }
  };

  load();
  return () => {
    ignore = true;
    controller.abort();
  };
}, [url]);
```

При смене `url` новый эффект включает loading заново. Cleanup помечает старый запрос как неактуальный до его `finally`, поэтому он не сбросит loading нового запроса. [Документация `useEffect`](https://react.dev/reference/react/useEffect).

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

1. [Нужен ли здесь useEffect? Раздел «Загрузка серверных данных»](https://habr.com/ru/articles/1055486/)
2. [Обновление React state после HTTP-запроса. Ulbi TV, с 1:37:12](https://www.youtube.com/watch?v=GNrdg3PzpJQ&t=5832s)

:::

---

## <strong>Какие паттерны для работы с асинхронностью в React?</strong> [#q-14bee738d69b81fcbaf4f8bab891faf9]

Паттерны для работы с асинхронностью в React

{/* prettier-ignore */}
1. <strong>Использование</strong> <code>useEffect</code>&#58;

    - Выполнение асинхронных операций при монтировании или обновлении компонента.

    - Пример&#58;

        ```javascript
        useEffect(() => {
          const fetchData = async () => {
            const response = await fetch('https://api.example.com/data');
            const result = await response.json();
            setData(result);
          };
          fetchData();
        }, []);
        ```

1. <strong>Использование</strong> <code>async</code><strong>/</strong><code>await</code>&#58;

    - Облегчение работы с асинхронными операциями внутри функций.

    - Пример&#58;

        ```javascript
        const fetchData = async () => {
          const response = await fetch('https://api.example.com/data');
          const result = await response.json();
          setData(result);
        };
        ```

1. <strong>Использование</strong> <code>axios</code>&#58;

    - Библиотека для упрощения HTTP-запросов.

    - Пример&#58;

        ```javascript
        import axios from 'axios';

        useEffect(() => {
          axios.get('https://api.example.com/data')
            .then(response => setData(response.data))
            .catch(error => console.error(error));
        }, []);
        ```

1. <strong>Использование</strong> <code>React Query</code>&#58;

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

    - Пример для React Query 3. В TanStack Query 5 используется пакет @tanstack/react-query и объект параметров useQuery&#58;

        ```javascript
        import { useQuery } from 'react-query';

        const { data, error, isLoading } = useQuery('data', () =>
          fetch('https://api.example.com/data').then(res => res.json())
        );
        ```

Паттерны для работы с асинхронностью в React включают использование хуков <code>useEffect</code>, синтаксиса <code>async</code>/<code>await</code>, библиотеки <code>axios</code>, и <code>React Query</code> для управления состоянием асинхронных данных.

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

1. [Получение данных, async/await и гонки ответов в useEffect](https://ru.react.dev/reference/react/useEffect)
   :::

---

## Как Promise.all ведет себя при отклонении одного Promise? [#q-transfer-0440]

`Promise.all` возвращает promise, который fulfilled массивом результатов в порядке входных элементов, когда выполнены все. Если любой вход отклоняется, общий promise отклоняется первой наблюдаемой причиной без ожидания результата остальных. Запущенные операции при этом не отменяются и могут продолжить менять состояние. Для отмены `fetch` нужен общий `AbortController`, а другие API должны поддерживать собственный механизм cancellation. Ошибки продолжающих операций следует учитывать, особенно если у них есть побочные эффекты. Если нужны все исходы, даже при части ошибок, используют `Promise.allSettled`.

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

1. [Promise.all: результаты и первое отклонение](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)
2. [Promise.all при ошибке одного Promise. Какие-то уроки \[Frontend\], с 39:46](https://www.youtube.com/watch?v=wx5qS8KlQAg&t=2386s)

:::

---

## Когда использовать Promise.allSettled вместо Promise.all? [#q-transfer-0441]

`Promise.allSettled` ждёт завершения всех входов и возвращает массив в исходном порядке. Каждый элемент имеет `status: fulfilled` с `value` либо `status: rejected` с `reason`. Он подходит для независимых запросов, где можно показать частичный результат, собрать все ошибки или выполнить пакет best-effort. `Promise.all` лучше, если без одного результата дальнейшая работа не имеет смысла и нужно рано перейти в обработку ошибки. `allSettled` не делает операцию успешной и не отменяет задачи; вызывающий код обязан разобрать оба статуса и решить, какие ошибки допустимы.

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

1. [Promise.allSettled и частичные результаты запросов](https://learn.javascript.ru/promise-api)
2. [Promise.allSettled и результаты всех операций. Какие-то уроки \[Frontend\], с 40:13](https://www.youtube.com/watch?v=wx5qS8KlQAg&t=2413s)

:::

---

## Как не допустить гонку ответов нескольких запросов в React? [#q-transfer-0442]

При смене параметра старый запрос отменяют в cleanup через `AbortController`, если транспорт поддерживает cancellation. Одной отмены недостаточно: ответ мог завершиться одновременно или библиотека не остановила всю цепочку. Поэтому каждому запуску присваивают request ID либо замыкают флаг актуальности и обновляют state только для последнего активного запроса. Cleanup также запрещает update после размонтирования. Библиотеки server state решают часть задачи по cache key, но mutation и ручные эффекты всё равно требуют ясной семантики. Ошибку `AbortError` не показывают как пользовательский сбой.

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

1. [useEffect: зависимости, cleanup и получение данных](https://ru.react.dev/reference/react/useEffect)
   :::

---

## Что именно выбирает Promise.race? [#q-transfer-0461]

`Promise.race` возвращает promise, который принимает состояние первого settled входа: fulfilled или rejected. Это не обязательно самый быстрый успешный результат. Таймаут часто реализуют гонкой операции с promise, который отклоняется после таймера, но проигравшая операция продолжает выполняться. Для `fetch` после таймаута нужно вызвать `AbortController.abort()` и очистить таймер; для других задач cancellation зависит от API. Пустой iterable оставляет результат pending навсегда. Порядок элементов влияет только если несколько входов уже settled к моменту обработки, поэтому на него не строят бизнес-гарантии.

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

1. [Promise.race: первый завершённый Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/race)
2. [Promise.race и первая завершившаяся операция. Какие-то уроки \[Frontend\], с 42:34](https://www.youtube.com/watch?v=wx5qS8KlQAg&t=2554s)

:::
