Робота з асинхронними операціями
1. React сам по собі - синхронна бібліотека
React не знає, коли і як ви завантажуєте дані, звертаєтеся до API чи виконуєте проміси.
Його завдання - відрендерити інтерфейс на основі стану (state і props).
Асинхронність з'являється тоді, коли ви змінюєте стан у результаті зовнішньої операції - і тоді React робить повторний рендер.
2. Типовий спосіб - через useEffect()
Асинхронні операції у функціональних компонентах зазвичай виконуються всередині useEffect, тому що:
- ефект виконується після рендеру,
- не можна робити
awaitнапряму в тілі компонента (рендер повинен бути чистою функцією).
Приклад:
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.
Приклад:
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:
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 лишається детермінованим і синхронним на рівні рендеру, а асинхронність - це спосіб зміни стану ззовні.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.