Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Робота з асинхронними операціями». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**React сам по собі - синхронна бібліотека**, яка нічого не знає про завантаження даних чи проміси; асинхронні операції зазвичай виконуються всередині `useEffect()`, оскільки ефект запускається після рендеру і `await` не можна викликати напряму в тілі компонента. **Ключове:** асинхронність у React - це не асинхронність самого React, а спосіб зміни стану ззовні; рендер лишається детермінованим і синхронним.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення### 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 лишається **детермінованим і синхронним** на рівні рендеру, а асинхронність - це **спосіб зміни стану ззовні**.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.