SWR example for data fetching
Client Component example using SWR: mark component with 'use client', define a fetcher function that calls fetch and returns r.json(), then use const { data, error, isLoading } = useSWR(url, fetcher). Handle loading and error states, then map over data.
use API with Suspense example
Server Component example: call getPosts() without await and pass the promise to <Posts>. Client Component example: use 'use client' directive, import { use } from 'react', and call const allPosts = use(posts) to resolve the promise. The <Posts> component must be wrapped in a <Suspense> boundary.
Community libraries for Client Component data fetching
You can use community libraries like SWR or React Query to fetch data in Client Components. These libraries have their own semantics for caching, streaming, and other features.
React use API for streaming data
Use React's use API to stream data from the server to client. In the Server Component, call the data fetching function without awaiting it and pass the promise as a prop to the Client Component. In the Client Component marked with 'use client', use the use() API to read the promise.
Use Suspense to coordinate loading UI at a boundary
Suspense should be used to define loading UI at a boundary and coordinate which parts of the interface reveal together or progressively, coordinating rendering while the data library and component structure determine when requests start.
Browser-driven interactions can use client-only fetching patterns
For browser-driven interactions such as autocomplete, either client-only fetching pattern (inline or Suspense) can be used. The initial result waits for hydration and a browser request, which is often the right tradeoff for data that is not needed until an interaction.
Provide initial data from Server Component when server knows what initial render needs
Initial data should be provided from a Server Component when the server knows what the initial render needs. The value can be included in the initial render or streamed through Suspense. The library receives it in the React Server Component payload and can continue managing it in the browser.
Data-fetching library stores browser value under shared cache identity
The data-fetching library stores the browser value under a shared cache identity that can be used for coordination with mutations and server invalidation.
Recommended client data-fetching libraries for shared browser cache
Use a client data-fetching library such as SWR, TanStack Query, or Apollo Client when Client Components need a shared browser cache. These libraries can add focus revalidation, interval polling, request deduplication, or optimistic updates across components.
Use Promise and React's use() to avoid data-fetching library when Client Component reads server data once
If a Client Component only needs to read server data once, pass it a Promise and unwrap it with React's `use()`. This avoids adding a library for data that never revalidates on the client.
Three client data-fetching patterns: inline, Suspense, and server-provided
Client data-fetching libraries support three common patterns. Inline loading states use `useSWR` (SWR) or `useQuery` (TanStack Query) and have data available after browser request and hydration. Suspense loading states use `useSWR` with `suspense: true` (SWR) or `useSuspenseQuery` (TanStack Query) and have data available after browser request and hydration. Provided by server uses `<SWRConfig fallback>` (SWR) or `<HydrationBoundary>` (TanStack Query) with data available on initial render or streamed from server.
Use inline loading states when each component renders its own loading UI
Inline loading states should be used when each component should render its own loading UI rather than coordinating loading UI at a boundary.
SWR client fetch example with error handling
Example: ProductAutocomplete component using useSWR with conditional key. When query is empty, key is null and request is delayed. The fetcher function calls fetch and throws on non-ok response. Component checks error and isLoading states and renders accordingly.
SWR with Suspense example
Example: ProductAutocomplete with Suspense wrapper. When query is provided, render Suspense boundary with fallback. Inside, ProductResults component calls useSWR with suspense: true option. Suspense handles the initial no-data state while the key is fetched.
SWR server-provided fallback example
Example: Page component provides SWRConfig with fallback. Server function getProduct(id) is called but not awaited in the fallback. ProductData wraps ProductView in SWRConfig. ProductView reads the same key with useSWR and suspense: true. Both use the same cache key from productCache.key(id).
SWR mutation with optimistic update example
Example: MarkReadButton component uses useSWRConfig mutate. Calls mutate with activityCache.key, async function that awaits markActivityReadAction and returns { count: 0 }, and options: optimisticData: { count: 0 }, revalidate: false, rollbackOnError: true, throwOnError: false.
SWR useSWR hook with conditional key for loading states
Use useSWR when the component should render its own loading and error states. A conditional key (passing null when not needed) delays the request until the interaction provides an input. The hook returns data, error, and isLoading properties. When data is not yet loaded, set a default value with the syntax const { data = [] }.
SWR with Suspense and suspense option
Use suspense: true when the nearest Suspense boundary should define the loading UI. With suspense: true, SWR defines data after Suspense resolves. Keep the interactive shell outside the Suspense boundary so it remains available while results load. Later revalidation keeps the current data rendered instead of showing the Suspense fallback again.
SWR isLoading vs isValidating states
The isLoading value is true when a request is running and there is no loaded data to display. The isValidating value is true whenever a request is running, including background revalidation. Use isValidating to provide background refresh feedback.
SWR Suspense parallel and sequential behavior
Independent Suspense reads can start in parallel when they render in sibling components. Multiple Suspense reads in one component run sequentially.
SWR server-provided data pattern with SWRConfig
When the initial render needs data and SWR should continue managing it in the browser, use the server-provided data pattern with SWR 2.3.0 and React 19. Scope SWRConfig to the route segment that owns the data. Provide a fallback property with initial data from the server. The fallback key and useSWR key must match exactly, or SWR ignores the fallback and fetches on the client.
SWR fallback data not awaited in provider
In SWRConfig, the fallback Promise is not awaited. Only components that read this key suspend. React passes the Promise through the React Server Component payload, and the component reading the matching key suspends until the data resolves.
SWR fallback treated as stale by default
By default, SWR treats fallback data as stale and starts a browser revalidation after hydration. SWR does not provide a time-based freshness window for fallback data. Set revalidateIfStale: false to skip revalidation when the hook mounts with cached data.
SWR revalidation triggers with fallback data
Focus, reconnect, polling, and mutate can still revalidate the key even with revalidateIfStale: false. To refresh on a schedule, set refreshInterval.
SWR browser cache independent from server cache
SWR owns a separate browser cache, so its revalidation options do not need to match cacheLife settings on the server function.
SWR mutate with optimisticData and rollback
Use useSWRConfig() to get the mutate function. Pass the SWR key, an async mutation function, and options including optimisticData, revalidate, rollbackOnError, and throwOnError. SWR shows the optimistic value immediately and rolls it back if the write fails.