Перейти к содержимому
На этой странице

Асинхронность

Все темы React Developer

Как выполнить 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

  1. Использование useEffect:

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

    • Пример:

      useEffect(() => {
        const fetchData = async () => {
          const response = await fetch('https://api.example.com/data');
          const result = await response.json();
          setData(result);
        };
        fetchData();
      }, []);
  2. Использование async/await:

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

    • Пример:

      const fetchData = async () => {
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();
        setData(result);
      };
  3. Использование axios:

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

    • Пример:

      import axios from 'axios';
      
      useEffect(() => {
        axios.get('https://api.example.com/data')
          .then(response => setData(response.data))
          .catch(error => console.error(error));
      }, []);
  4. Использование 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.


Когда использовать Promise.allSettled вместо Promise.all?

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

Собеседования: React

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: React-разработчик, Frontend-разработчик. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.