Асинхронность
Как выполнить HTTP-запросы в React?
Для выполнения HTTP-запросов в React можно использовать стандартные методы, такие как fetch или библиотеки, такие как axios.
Пример с использованием fetch:
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;
Пример с использованием axios:
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. Запрос по действию пользователя запускайте из обработчика события. Кеширование и повторную загрузку удобнее поручить библиотеке или загрузчику маршрута.
Ссылки для изучения
Как обновить состояние React-компонента после асинхронной операции?
После завершения операции вызовите setter из useState. Если запрос запускается из эффекта, не делайте сам callback useEffect асинхронным: объявите async-функцию внутри эффекта и вызовите её. Храните отдельно данные, состояние загрузки и ошибку.
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.
Ссылки для изучения
Какие паттерны для работы с асинхронностью в React?
Паттерны для работы с асинхронностью в React
-
Использование
useEffect:-
Выполнение асинхронных операций при монтировании или обновлении компонента.
-
Пример:
useEffect(() => { const fetchData = async () => { const response = await fetch('https://api.example.com/data'); const result = await response.json(); setData(result); }; fetchData(); }, []);
-
-
Использование
async/await:-
Облегчение работы с асинхронными операциями внутри функций.
-
Пример:
const fetchData = async () => { const response = await fetch('https://api.example.com/data'); const result = await response.json(); setData(result); };
-
-
Использование
axios:-
Библиотека для упрощения HTTP-запросов.
-
Пример:
import axios from 'axios'; useEffect(() => { axios.get('https://api.example.com/data') .then(response => setData(response.data)) .catch(error => console.error(error)); }, []);
-
-
Использование
React Query:-
Библиотека для управления состоянием асинхронных данных.
-
Пример для React Query 3. В TanStack Query 5 используется пакет @tanstack/react-query и объект параметров useQuery:
import { useQuery } from 'react-query'; const { data, error, isLoading } = useQuery('data', () => fetch('https://api.example.com/data').then(res => res.json()) );
-
Паттерны для работы с асинхронностью в React включают использование хуков useEffect, синтаксиса async/await, библиотеки axios, и React Query для управления состоянием асинхронных данных.
Ссылки для изучения
Как Promise.all ведет себя при отклонении одного Promise?
Promise.all возвращает promise, который fulfilled массивом результатов в порядке входных элементов, когда выполнены все. Если любой вход отклоняется, общий promise отклоняется первой наблюдаемой причиной без ожидания результата остальных. Запущенные операции при этом не отменяются и могут продолжить менять состояние. Для отмены fetch нужен общий AbortController, а другие API должны поддерживать собственный механизм cancellation. Ошибки продолжающих операций следует учитывать, особенно если у них есть побочные эффекты. Если нужны все исходы, даже при части ошибок, используют Promise.allSettled.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- СОБЕСЕДОВАНИЕ НА FRONTEND РАЗРАБОТЧИКА | REACT TYPESCRIPT · 25:19–25:45Мок-собеседование · Совместный разбор
В обсуждении уточняют, что Promise.all сам возвращает промис: при успехе всех операций — массив результатов, при отказе одной — её ошибку.
Когда использовать Promise.allSettled вместо Promise.all?
Promise.allSettled ждёт завершения всех входов и возвращает массив в исходном порядке. Каждый элемент имеет status: fulfilled с value либо status: rejected с reason. Он подходит для независимых запросов, где можно показать частичный результат, собрать все ошибки или выполнить пакет best-effort. Promise.all лучше, если без одного результата дальнейшая работа не имеет смысла и нужно рано перейти в обработку ошибки. allSettled не делает операцию успешной и не отменяет задачи; вызывающий код обязан разобрать оба статуса и решить, какие ошибки допустимы.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- СОБЕСЕДОВАНИЕ НА FRONTEND РАЗРАБОТЧИКА | REACT TYPESCRIPT · 27:23–28:20Мок-собеседование · Ответ кандидата
Кандидат предлагает Promise.allSettled, когда нужны результаты всех операций, и объясняет, что по каждому результату можно отдельно определить успех или ошибку.
Как не допустить гонку ответов нескольких запросов в React?
При смене параметра старый запрос отменяют в cleanup через AbortController, если транспорт поддерживает cancellation. Одной отмены недостаточно: ответ мог завершиться одновременно или библиотека не остановила всю цепочку. Поэтому каждому запуску присваивают request ID либо замыкают флаг актуальности и обновляют state только для последнего активного запроса. Cleanup также запрещает update после размонтирования. Библиотеки server state решают часть задачи по cache key, но mutation и ручные эффекты всё равно требуют ясной семантики. Ошибку AbortError не показывают как пользовательский сбой.
Ссылки для изучения
Что именно выбирает Promise.race?
Promise.race возвращает promise, который принимает состояние первого settled входа: fulfilled или rejected. Это не обязательно самый быстрый успешный результат. Таймаут часто реализуют гонкой операции с promise, который отклоняется после таймера, но проигравшая операция продолжает выполняться. Для fetch после таймаута нужно вызвать AbortController.abort() и очистить таймер; для других задач cancellation зависит от API. Пустой iterable оставляет результат pending навсегда. Порядок элементов влияет только если несколько входов уже settled к моменту обработки, поэтому на него не строят бизнес-гарантии.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- РЕАЛЬНОЕ СОБЕСЕДОВАНИЕ С КУЧЕЙ ЗАДАЧ НА MIDDLE/SENIOR FRONTEND РАЗРАБОТЧИКА! ЗП ДО 300К · 19:09–19:34Техническое собеседование · Ответ кандидата
Кандидат различает Promise.race, выбирающий первый завершившийся промис, и Promise.any, ожидающий первый успешный результат.







