Skip to main content

Робота з асинхронними операціями

1. React сам по собі - синхронна бібліотека

React не знає, коли і як ви завантажуєте дані, звертаєтеся до API чи виконуєте проміси. Його завдання - відрендерити інтерфейс на основі стану (state і props). Асинхронність з'являється тоді, коли ви змінюєте стан у результаті зовнішньої операції - і тоді React робить повторний рендер.


2. Типовий спосіб - через useEffect()

Асинхронні операції у функціональних компонентах зазвичай виконуються всередині useEffect, тому що:

  • ефект виконується після рендеру,
  • не можна робити await напряму в тілі компонента (рендер повинен бути чистою функцією).

Приклад:

javascript
import { useState, useEffect } from "react"; function UserProfile({ userId }) { const [user, setUser] = useState(null); useEffect(() => { let isMounted = true; async function fetchUser() { const res = await fetch(`/api/users/${userId}`); const data = await res.json(); if (isMounted) setUser(data); } fetchUser(); // cleanup - якщо компонент розмонтується до завершення запиту return () => { isMounted = false; }; }, [userId]); if (!user) return <p>Loading...</p>; return <p>Hello, {user.name}</p>; }

Важливо: useEffect не можна зробити async напряму - замість цього створюють вкладену async-функцію.


3. Асинхронні операції = побічні ефекти

Класичні приклади:

  • завантаження даних з API (fetch, axios, GraphQL);
  • взаємодія з WebSocket чи SSE;
  • таймери (setTimeout, setInterval);
  • операції з локальним сховищем (localStorage, IndexedDB);
  • робота із зовнішніми SDK (наприклад, Firebase).

Усі вони виконуються поза React, але впливають на стан.


4. Сучасні підходи

React Query (TanStack Query)

Один із найпопулярніших способів роботи з асинхронними даними - TanStack Query. Він:

  • кешує результати;
  • автоматично повторює запити при фокусі вікна;
  • підтримує пагінацію, інвалідацію, optimistic updates.

Приклад:

javascript
import { useQuery } from "@tanstack/react-query"; function UserProfile({ userId }) { const { data, isLoading } = useQuery({ queryKey: ["user", userId], queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()), }); if (isLoading) return <p>Loading...</p>; return <p>Hello, {data.name}</p>; }

5. Асинхронність у React 18+ (Concurrent features)

React 18 представив нові можливості для асинхронного рендеру:

  • startTransition() - дозволяє позначити оновлення як "незначні", щоб не блокувати UI.
  • useTransition() і useDeferredValue() - дозволяють відкласти рендер або плавно оновлювати UI.
  • Suspense + React.lazy() - для лінивого завантаження компонентів і очікування даних.

Приклад із Suspense:

javascript
const UserProfile = React.lazy(() => import("./UserProfile")); function App() { return ( <Suspense fallback={<p>Loading...</p>}> <UserProfile /> </Suspense> ); }

У React Server Components (RSC) асинхронність вбудована - серверні компоненти можуть бути async і використовувати await прямо в тілі.


6. Ключова ідея

Асинхронність у React не дорівнює асинхронності самого React. React лишається детермінованим і синхронним на рівні рендеру, а асинхронність - це спосіб зміни стану ззовні.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.