Data Fetching

Data fetching is a core part of any application. This page goes through how you can fetch, cache, and revalidate data in React and Next.js.

Data Fetching on the Server with Fetch

You can use fetch with async/await in Server Components, in Route Handlers, and in Server Actions.

Example

app/page.tsx
1async function getData() {
2  const res = await fetch('https://api.example.com/...')
3  // The return value is *not* serialized
4  // You can return Date, Map, Set, etc.
5 
6  if (!res.ok) {
7    // This will activate the closest `error.js`  Error Boundary
8    throw new Error('Failed to fetch data')
9  }
10 
11  return res.json()
12}
13 
14export default async function Page() {
15  const data = await getData()
16 
17  return <main></main>
18}

Tip : To use async/await in a Server Component with TypeScript, you'll need to use TypeScript 5.1.3 or higher and @types/react 18.2.8 or higher.

Data Caching

Caching stores data so it doesn't need to be re-fetched from your data source on every request.

By default, Next.js automatically caches the returned values of fetch in the Data Cache on the server. This means that the data can be fetched at build time or request time, cached, and reused on each data request.

app/page.tsx
1// 'force-cache' is the default, and can be omitted
2fetch('https://...', { cache: 'force-cache' })

fetch requests that use the POST method are also automatically cached. Unless it's inside a Route Handler that uses the POST method, then it will not be cached.

Revalidating Data

Revalidation is the process of purging the Data Cache and re-fetching the latest data. This is useful when your data changes and you want to ensure you show the latest information.

Cached data can be revalidated in two ways:

  • - Time-based revalidation: Automatically revalidate data after a certain amount of time has passed. This is useful for data that changes infrequently and freshness is not as critical.
  • - On-demand revalidation: Manually revalidate data based on an event (e.g. form submission). On-demand revalidation can use a tag-based or path-based approach to revalidate groups of data at once.

Time-based Revalidation

To revalidate data at a timed interval, you can use the option of fetch to set the cache lifetime of a resource (in seconds).

app/page.tsx
1fetch('https://...', { next: { revalidate: 3600 } })

On-Demand Revalidation

Data can be revalidated on-demand by path (revalidatePath) or by cache tag (revalidateTag)

app/page.tsx
1export default async function Page() {
2  const res = await fetch('https://...', { next: { tags: ['collection'] } })
3  const data = await res.json()
4  // ...
5}

You can then revalidate this fetch call tagged with collection by calling revalidateTag in a Server Action:

app/action
1'use server'
2 
3import { revalidateTag } from 'next/cache'
4 
5export default async function action() {
6  revalidateTag('collection')
7}