Suggest an editImprove this articleRefine the answer for “Suspense and data fetching”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`React.Suspense`** lets you defer a component's render until its data is ready, showing a fallback instead of a manual `loading` state. **Key point:** React itself pauses the render when a component throws a `Promise`, shows the fallback from the nearest `<Suspense>`, and automatically resumes the render once the promise resolves, without `useEffect` and `setState`.Shown above the full answer for quick recall.Answer (EN)Image## 1. The problem without `Suspense` In a "classic" React application, data fetching looks like this: ```javascript function Profile() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { fetch('/api/user') .then(res => res.json()) .then(setUser) .finally(() => setLoading(false)); }, []); if (loading) return <p>Loading...</p>; return <h1>{user.name}</h1>; } ``` Drawbacks of this approach: - you have to manually manage the `loading` / `error` / `data` states; - the code gets cluttered with this logic; - the UI **"flashes"** on every transition (the loader is visible); - React can't "pause" the render and show old data; - there's no built-in way to synchronize several async components. --- ## 2. What `Suspense` does > `React.Suspense` lets you **defer a component's render** > until its data is ready, > and show a **fallback** instead of a manual `loading` state. That is, React itself can "wait" for asynchronous data, without you needing to manually write `useEffect` and `useState`. --- ## 3. How it works conceptually When React encounters a component in the tree that **isn't ready yet** (for example, it throws a `Promise`), React: 1. **pauses** rendering that part of the tree; 2. shows the `fallback` from the nearest `<Suspense>`; 3. once the promise resolves, **rendering resumes** automatically. --- ## 4. An example with `SWR` and Suspense The **SWR** library works with `Suspense` out of the box. ```javascript import useSWR from "swr"; import { Suspense } from "react"; const fetcher = (url) => fetch(url).then(res => res.json()); function UserProfile() { const { data } = useSWR("/api/user", fetcher, { suspense: true }); return <h1>Hello, {data.name}</h1>; } export default function App() { return ( <Suspense fallback={<p>Loading profile...</p>}> <UserProfile /> </Suspense> ); } ``` What happens: - on the first call, `useSWR` throws a `Promise` until the data arrives; - React "catches" that `Promise` and **stops the render**; - it shows the `fallback`; - once the request finishes, React automatically **re-renders the component** with the ready data. No `loading`, `useEffect`, `setState`: React itself "waits". --- ## 5. Why this is great ### Less manual code No need to manually manage `loading` / `error`. ### Composition of async components Several components inside a `Suspense` can wait for their data at the same time: ```javascript <Suspense fallback={<DashboardSkeleton />}> <UserProfile /> <UserStats /> <RecentActivities /> </Suspense> ``` React waits until all three get their data, and shows them at once, **without piecemeal flickering**. ### Smooth UX The old content stays on screen, React shows the fallback *only for the new data*, instead of "clearing" the whole screen. --- ## 6. Suspense + `startTransition` = smooth updates React 18 introduced **concurrent rendering**, and now `Suspense` can be used for **smooth data transitions**. ```javascript import { useState, Suspense, startTransition } from "react"; import useSWR from "swr"; function SearchResults({ query }) { const { data } = useSWR(`/api/search?q=${query}`, fetcher, { suspense: true }); return <ul>{data.results.map(r => <li key={r}>{r}</li>)}</ul>; } export function Search() { const [query, setQuery] = useState(''); return ( <> <input value={query} onChange={e => { const value = e.target.value; startTransition(() => setQuery(value)); }} placeholder="Search..." /> <Suspense fallback={<p>Loading...</p>}> <SearchResults query={query} /> </Suspense> </> ); } ``` What React does: - it doesn't block input (`startTransition`); - under the hood, it pauses updating `SearchResults` until the data arrives; - it shows the fallback only for the "new state". The result: a responsive interface, smooth search, no flickering or delays. --- ## 7. Suspense and **React Server Components (Next.js 13+)** On the server (the App Router in Next.js), `Suspense` is used for **streaming rendering (Streaming SSR)**. ```javascript // app/page.tsx export default async function Page() { return ( <> <Header /> <Suspense fallback={<PostsSkeleton />}> <Posts /> {/* an async component */} </Suspense> </> ); } ``` Here React: - renders the page on the server; - immediately sends the user the ready parts (Header, layout); - later "fills in" the rest once `Posts` has loaded. The UX is like an SPA, but with SSR: the page appears instantly, and data loads in pieces. --- ## 8. Comparing approaches | Approach | What it does | Downsides | |---|---|---| | useEffect + useState | Manual loading management | Code duplication, UI "flashing" | | SWR / React Query (without Suspense) | Cache + state flags | A bit more complex when composing | | Suspense | React itself waits for the data and manages the UI | Requires a compatible library (SWR, RQ, RSC) | --- ## SUMMARY | What Suspense does during data fetching | Why it matters | |---|---| | Pauses the render until the data is ready | Avoids an "empty" UI | | Shows a fallback instead of a manual loader | Simplifies the code | | Resumes the render automatically | No need for `useEffect` and `setState` | | Works with several data sources | Enables parallel loading | | Integrates with concurrent rendering | Smooth transitions without blocking | | Used in Server Components | Streaming SSR | --- ### In short: > `React.Suspense` **lets React "wait" for data asynchronously during data fetching, showing a fallback,** > **and then automatically continue the render once the data arrives.** > > This makes the code simpler, the interface smoother, and the UX instant and predictable.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.