Menu
next-query

revalidate

Revalidate a tag, or a query key, from server actions and route handlers.

revalidate() expires a tag, so the next read of anything that carries it runs again.

Signature

@angelitolm/next-query
ts
function revalidate(key: QueryKey | string): void
  • A string is a tag: revalidate('products') expires exactly the tag products. It must be 1 to 256 characters, otherwise it throws a TypeError.
  • A key (an array) expires the key's deepest tag: revalidate(['products', 1]) is revalidate('products/1').

Both call revalidateTag(tag, { expire: 0 }).

app/actions.ts
ts
'use server'
import { revalidate } from '@angelitolm/next-query'
 
export async function renameProduct(id: string, name: string) {
  await db.rename(id, name)
  revalidate('products') // every fetch and query that carries the tag 'products'
}

Tag semantics

revalidate expires one tag, and every entry that carries that tag. Which entries carry it is up to how you tagged them:

Tagged withrevalidate('products')revalidate(['products', 1])
['products']yesno
tags(['products', 1]), that is ['products', 'products/1']yesyes
tags(['products', 2]), that is ['products', 'products/2']yesno

Tag from general to specific with tags() and one call can refresh a whole branch.

Where to call it

Call it from server actions and route handlers, after you have changed the data. Next does not allow revalidating while a page renders.

app/api/products/route.ts
ts
import { revalidate } from '@angelitolm/next-query'
 
export async function POST(request: Request) {
  await db.create(await request.json())
  revalidate('products')
  return Response.json({ ok: true })
}

An invalid key throws the same TypeError as query().

Under the hood

revalidate() calls revalidateTag(<the tag>, { expire: 0 }). expire: 0 expires the entry right away on Next 16; on Next 15, revalidateTag takes no second argument and ignores it. The same code works on both.

The name clash with export const revalidate

A page can export a route segment option called revalidate. If you import revalidate from next-query into the same file, the two collide (the name 'revalidate' is already declared). Rename the import:

app/products/page.tsx
tsx
import { revalidate as revalidateQuery } from '@angelitolm/next-query'
 
export const revalidate = 60

The segment option and the library function are unrelated. In files without that export, the plain name is fine.