Movatterモバイル変換


[0]ホーム

URL:


Skip to content
App RouterGetting StartedFetching Data

Fetching Data

This page will walk you through how you can fetch data inServer and Client Components, and how tostream components that depend on data.

Fetching data

Server Components

You can fetch data in Server Components using:

  1. Thefetch API
  2. AnORM or database

With thefetch API

To fetch data with thefetch API, turn your component into an asynchronous function, and await thefetch call. For example:

app/blog/page.tsx
exportdefaultasyncfunctionPage() {constdata=awaitfetch('https://api.vercel.app/blog')constposts=awaitdata.json()return (    <ul>      {posts.map((post)=> (        <likey={post.id}>{post.title}</li>      ))}    </ul>  )}

Good to know:

  • fetch responses are not cached by default. However, Next.js willprerender the route and the output will be cached for improved performance. If you'd like to opt intodynamic rendering, use the{ cache: 'no-store' } option. See thefetch API Reference.
  • During development, you can logfetch calls for better visibility and debugging. See thelogging API reference.

With an ORM or database

Since Server Components are rendered on the server, you can safely make database queries using an ORM or database client. Turn your component into an asynchronous function, and await the call:

app/blog/page.tsx
import { db, posts }from'@/lib/db'exportdefaultasyncfunctionPage() {constallPosts=awaitdb.select().from(posts)return (    <ul>      {allPosts.map((post)=> (        <likey={post.id}>{post.title}</li>      ))}    </ul>  )}

Client Components

There are two ways to fetch data in Client Components, using:

  1. React'suse hook
  2. A community library likeSWR orReact Query

Streaming data with theuse hook

You can use React'suse hook tostream data from the server to client. Start by fetching data in your Server component, and pass the promise to your Client Component as prop:

app/blog/page.tsx
import Postsfrom'@/app/ui/postsimport { Suspense }from'react'exportdefaultfunctionPage() {// Don't await the data fetching functionconstposts=getPosts()return (    <Suspensefallback={<div>Loading...</div>}>      <Postsposts={posts} />    </Suspense>  )}

Then, in your Client Component, use theuse hook to read the promise:

app/ui/posts.tsx
'use client'import { use }from'react'exportdefaultfunctionPosts({  posts,}: {  posts:Promise<{ id:string; title:string }[]>}) {constallPosts=use(posts)return (    <ul>      {allPosts.map((post)=> (        <likey={post.id}>{post.title}</li>      ))}    </ul>  )}

In the example above, the<Posts> component is wrapped in a<Suspense> boundary. This means the fallback will be shown while the promise is being resolved. Learn more aboutstreaming.

Community libraries

You can use a community library likeSWR orReact Query to fetch data in Client Components. These libraries have their own semantics for caching, streaming, and other features. For example, with SWR:

app/blog/page.tsx
'use client'import useSWRfrom'swr'constfetcher= (url)=>fetch(url).then((r)=>r.json())exportdefaultfunctionBlogPage() {const {data,error,isLoading }=useSWR('https://api.vercel.app/blog',    fetcher  )if (isLoading)return <div>Loading...</div>if (error)return <div>Error: {error.message}</div>return (    <ul>      {data.map((post: { id:string; title:string })=> (        <likey={post.id}>{post.title}</li>      ))}    </ul>  )}

Deduplicate requests and cache data

One way to deduplicatefetch requests is withrequest memoization. With this mechanism,fetch calls usingGET orHEAD with the same URL and options in a single render pass are combined into one request. This happens automatically, and you canopt out by passing an Abort signal tofetch.

Request memoization is scoped to the lifetime of a request.

You can also deduplicatefetch requests by using Next.js’Data Cache, for example by settingcache: 'force-cache' in yourfetch options.

Data Cache allows sharing data across the current render pass and incoming requests.

If you arenot usingfetch, and instead using an ORM or database directly, you can wrap your data access with theReactcache function.

app/lib/data.ts
import { cache }from'react'import { db, posts, eq }from'@/lib/db'exportconstgetPost=cache(async (id:string)=> {constpost=awaitdb.query.posts.findFirst({    where:eq(posts.id,parseInt(id)),  })})

Streaming

Warning: The content below assumes thedynamicIO config option is enabled in your application. The flag was introduced in Next.js 15 canary.

When usingasync/await in Server Components, Next.js will opt intodynamic rendering. This means the data will be fetched and rendered on the server for every user request. If there are any slow data requests, the whole route will be blocked from rendering.

To improve the initial load time and user experience, you can use streaming to break up the page's HTML into smaller chunks and progressively send those chunks from the server to the client.

How Server Rendering with Streaming WorksHow Server Rendering with Streaming Works

There are two ways you can implement streaming in your application:

  1. Wrapping a page with aloading.js file
  2. Wrapping a component with<Suspense>

Withloading.js

You can create aloading.js file in the same folder as your page to stream theentire page while the data is being fetched. For example, to streamapp/blog/page.js, add the file inside theapp/blog folder.

Blog folder structure with loading.js fileBlog folder structure with loading.js file
app/blog/loading.tsx
exportdefaultfunctionLoading() {// Define the Loading UI herereturn <div>Loading...</div>}

On navigation, the user will immediately see the layout and aloading state while the page is being rendered. The new content will then be automatically swapped in once rendering is complete.

Loading UILoading UI

Behind-the-scenes,loading.js will be nested insidelayout.js, and will automatically wrap thepage.js file and any children below in a<Suspense> boundary.

loading.js overviewloading.js overview

This approach works well for route segments (layouts and pages), but for more granular streaming, you can use<Suspense>.

With<Suspense>

<Suspense> allows you to be more granular about what parts of the page to stream. For example, you can immediately show any page content that falls outside of the<Suspense> boundary, and stream in the list of blog posts inside the boundary.

app/blog/page.tsx
import { Suspense }from'react'import BlogListfrom'@/components/BlogList'import BlogListSkeletonfrom'@/components/BlogListSkeleton'exportdefaultfunctionBlogPage() {return (    <div>      {/* This content will be sent to the client immediately */}      <header>        <h1>Welcome to the Blog</h1>        <p>Read the latest posts below.</p>      </header>      <main>        {/* Any content wrapped in a <Suspense> boundary will be streamed */}        <Suspensefallback={<BlogListSkeleton />}>          <BlogList />        </Suspense>      </main>    </div>  )}

Creating meaningful loading states

An instant loading state is fallback UI that is shown immediately to the user after navigation. For the best user experience, we recommend designing loading states that are meaningful and help users understand the app is responding. For example, you can use skeletons and spinners, or a small but meaningful part of future screens such as a cover photo, title, etc.

In development, you can preview and inspect the loading state of your components using theReact Devtools.

Examples

Sequential data fetching

Sequential data fetching happens when nested components in a tree each fetch their own data and the requests are notdeduplicated, leading to longer response times.

Sequential and Parallel Data FetchingSequential and Parallel Data Fetching

There may be cases where you want this pattern because one fetch depends on the result of the other.

For example, the<Playlists> component will only start fetching data once the<Artist> component has finished fetching data because<Playlists> depends on theartistID prop:

app/artist/[username]/page.tsx
exportdefaultasyncfunctionPage({  params,}: {  params:Promise<{ username:string }>}) {const {username }=await params// Getartist informationconstartist=awaitgetArtist(username)return (    <>      <h1>{artist.name}</h1>      {/* Show fallback UI while the Playlists component is loading */}      <Suspensefallback={<div>Loading...</div>}>        {/* Pass theartist ID to the Playlists component */}        <PlaylistsartistID={artist.id} />      </Suspense>    </>  )}asyncfunctionPlaylists({artistID }: {artistID:string }) {// Use theartist ID to fetch playlistsconstplaylists=awaitgetArtistPlaylists(artistID)return (    <ul>      {playlists.map((playlist)=> (        <likey={playlist.id}>{playlist.name}</li>      ))}    </ul>  )}

To improve the user experience, you should useReact<Suspense> to show afallback while data is being fetch. This will enablestreaming and prevent the whole route from being blocked by the sequential data requests.

Parallel data fetching

Parallel data fetching happens when data requests in a route are eagerly initiated and start at the same time.

By default,layouts and pages are rendered in parallel. So each segment starts fetching data as soon as possible.

However, withinany component, multipleasync/await requests can still be sequential if placed after the other. For example,getAlbums will be blocked untilgetArtist is resolved:

app/artist/[username]/page.tsx
import { getArtist, getAlbums }from'@/app/lib/data'exportdefaultasyncfunctionPage({ params }) {// These requests will be sequentialconst {username }=await paramsconstartist=awaitgetArtist(username)constalbums=awaitgetAlbums(username)return <div>{artist.name}</div>}

You can initiate requests in parallel by defining them outside the components that use the data, and resolving them together, for example, withPromise.all:

app/artist/[username]/page.tsx
import Albumsfrom'./albums'asyncfunctiongetArtist(username:string) {constres=awaitfetch(`https://api.example.com/artist/${username}`)returnres.json()}asyncfunctiongetAlbums(username:string) {constres=awaitfetch(`https://api.example.com/artist/${username}/albums`)returnres.json()}exportdefaultasyncfunctionPage({  params,}: {  params:Promise<{ username:string }>}) {const {username }=await paramsconstartistData=getArtist(username)constalbumsData=getAlbums(username)// Initiate both requests in parallelconst [artist,albums]=awaitPromise.all([artistData, albumsData])return (    <>      <h1>{artist.name}</h1>      <Albumslist={albums} />    </>  )}

Good to know: If one request fails when usingPromise.all, the entire operation will fail. To handle this, you can use thePromise.allSettled method instead.

Preloading data

You can preload data by creating an utility function that you eagerly call above blocking requests.<Item> conditionally renders based on thecheckIsAvailable() function.

You can callpreload() beforecheckIsAvailable() to eagerly initiate<Item/> data dependencies. By the time<Item/> is rendered, its data has already been fetched.

app/item/[id]/page.tsx
import { getItem, checkIsAvailable }from'@/lib/data'exportdefaultasyncfunctionPage({  params,}: {  params:Promise<{ id:string }>}) {const {id }=await params// starting loadingitem datapreload(id)// perform another asynchronous taskconstisAvailable=awaitcheckIsAvailable()return isAvailable? <Itemid={id} />:null}exportconstpreload= (id:string)=> {// void evaluates the given expression and returns undefined// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/voidvoidgetItem(id)}exportasyncfunctionItem({ id }: { id:string }) {constresult=awaitgetItem(id)// ...}

Additionally, you can use React'scache function and theserver-only package to create a reusable utility function. This approach allows you to cache the data fetching function and ensure that it's only executed on the server.

utils/get-item.ts
import { cache }from'react'import'server-only'import { getItem }from'@/lib/data'exportconstpreload= (id:string)=> {voidgetItem(id)}exportconstgetItem=cache(async (id:string)=> {// ...})

API Reference

Learn more about the features mentioned in this page by reading the API Reference.

Data Security

Learn the built-in data security features in Next.js and learn best practices for protecting your application's data.

fetch

API reference for the extended fetch function.

loading.js

API reference for the loading.js file.

logging

Configure how data fetches are logged to the console when running Next.js in development mode.

taint

Enable tainting Objects and Values.

Was this helpful?

supported.

[8]ページ先頭

©2009-2025 Movatter.jp