Open In App

Next.js Functions: revalidateTag

Last Updated : 28 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Next.js has the revalidateTag function that can be used to selectively invalidate cached data on demand for a specific cache tag. This allows developers to ensure that dynamic content is refreshed and served up-to-date without waiting for the entire cache to expire. It's a powerful feature for maintaining data consistency and optimizing performance in applications where content frequently changes.

revalidateTag Function

The revalidateTag function in Next.js is used to clear the cache for a specific tag, ensuring that updated content is served the next time that path is accessed. It works in both Node.js and Edge runtimes and only triggers revalidation when the path is revisited. The function takes a single-string parameter for the cache tag and doesn't return a value.

Syntax:

revalidateTag(tag: string): void

Parameters:

tag: A string representing the cache tag associated with the data you want to revalidate. It must be less than or equal to 256 characters and is case-sensitive.

Return Value:

revalidateTag does not return a value.

Server Action

A Server Action in Next.js is a function that runs exclusively on the server. It allows you to perform server-side logic, such as interacting with databases, calling external APIs, or revalidating cache, without exposing this logic to the client.

Example: The server action updates the like count in the database and revalidates the cache. In the below code, likePost is a server action that updates the like count of a post in the database and then revalidates the cache tag 'postLikes' to make sure the UI reflects the latest like count.

JavaScript
// app/actions.js

'use server'

import { revalidateTag } from 'next/cache'
import { updateLikeCount } from './database' 

// Server action to like a post and revalidate the cache
export default async function likePost(postId) {
 // Update the like count for the post in the database
    await updateLikeCount(postId) 
    // Revalidate the cache for the 'postLikes' tag
    revalidateTag('postLikes')  
}

Route Handler

A Route Handler in Next.js defines how specific API routes respond to requests. It handles HTTP methods (like GET, POST, etc.) and can interact with server-side resources, such as revalidating cache, just like server actions. This route handler listens for DELETE requests at /api/deletePost. When a request is received, it extracts the post ID from the query parameters, deletes the corresponding post from the database, and revalidates the 'posts' cache tag to ensure the cache is updated.

Example: This route handler deletes a post based on the post ID sent in a DELETE request. After deletion, it revalidates the cache.

JavaScript
// app/api/deletePost/route.js

import { revalidateTag } from 'next/cache'
import { deletePostById } from './database'  

// Route handler to delete a post and revalidate cache
export async function DELETE(request) {
    const postId = request.nextUrl.searchParams.get('id')  
     // Delete the post from the database
    await deletePostById(postId) 
    // Revalidate the cache for the 'posts' tag
    revalidateTag('posts')  
    return new Response(JSON.stringify({ success: true }), { status: 200 })  
}

Steps To Implement revalidateTag Function

Step 1: Create a Next.js application using the following command.

npx create-next-app@latest gfg

Step 2: It will ask you some questions, so choose the following.

√ Would you like to use TypeScript? ... No
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... No
√ Would you like to use `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@/*)? ... Yes

Step 3: After creating your project folder i.e. gfg, move to it using the following command.

cd gfg

Folder Structure:

PS
Project Structurey

Dependencies:

"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.2.5"
}

Example: In the below example, revalidateTag is used to invalidate the cache for a specific tag ('posts') after a new post is added. When the form is submitted, it simulates adding a post and then triggers cache revalidation for the 'posts' tag. The cache invalidation only occurs the next time the relevant path is visited, ensuring up-to-date content is served. Additionally, a route handler is provided to trigger revalidation via a URL query parameter.

CSS
/* src/app/globals.css */

:root {
  --max-width: 1100px;
  --border-radius: 12px;
  --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
    "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
    "Fira Mono", "Droid Sans Mono", "Courier New", monospace;

  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;

  --primary-glow: conic-gradient(from 180deg at 50% 50%,
      #16abff33 0deg,
      #0885ff33 55deg,
      #54d6ff33 120deg,
      #0071ff33 160deg,
      transparent 360deg);
  --secondary-glow: radial-gradient(rgba(255, 255, 255, 1),
      rgba(255, 255, 255, 0));

  --tile-start-rgb: 239, 245, 249;
  --tile-end-rgb: 228, 232, 233;
  --tile-border: conic-gradient(#00000080,
      #00000040,
      #00000030,
      #00000020,
      #00000010,
      #00000010,
      #00000080);

  --callout-rgb: 238, 240, 241;
  --callout-border-rgb: 172, 175, 176;
  --card-rgb: 180, 185, 188;
  --card-border-rgb: 131, 134, 135;
}

@media (prefers-color-scheme: dark) {
  :root {
    --foreground-rgb: 255, 255, 255;
    --background-start-rgb: 0, 0, 0;
    --background-end-rgb: 0, 0, 0;

    --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
    --secondary-glow: linear-gradient(to bottom right,
        rgba(1, 65, 255, 0),
        rgba(1, 65, 255, 0),
        rgba(1, 65, 255, 0.3));

    --tile-start-rgb: 2, 13, 46;
    --tile-end-rgb: 2, 5, 19;
    --tile-border: conic-gradient(#ffffff80,
        #ffffff40,
        #ffffff30,
        #ffffff20,
        #ffffff10,
        #ffffff10,
        #ffffff80);

    --callout-rgb: 20, 20, 20;
    --callout-border-rgb: 108, 108, 108;
    --card-rgb: 100, 100, 100;
    --card-border-rgb: 200, 200, 200;
  }
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

html,
body {
  max-width: 100vw;
  overflow-x: hidden;
}

body {
  color: rgb(var(--foreground-rgb));
  background: linear-gradient(to bottom,
      transparent,
      rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb));
}

a {
  color: inherit;
  text-decoration: none;
}

@media (prefers-color-scheme: dark) {
  html {
    color-scheme: dark;
  }
}
JavaScript
// src/app/page.js

'use client'

import { useState } from 'react';

export default function Page() {
  const [postTitle, setPostTitle] = useState('');
  const [message, setMessage] = useState('');

  async function handleSubmit(e) {
    e.preventDefault();

    // Simulate adding a post (could be an API call)
    await addPost(postTitle);

    // Revalidate the cache for the 'posts' tag
    const response = await fetch('/api/revalidate?tag=posts');
    const result = await response.json();

    // Show a confirmation message
    if (result.revalidated) {
      setMessage(`Post "${postTitle}" added and cache revalidated!`);
    }
  }

  async function addPost(title) {
    // Simulate a delay for adding a post
    return new Promise((resolve) => {
      setTimeout(() => resolve({ success: true }), 1000);
    });
  }

  return (
    <div style={{ marginTop: '50px' }}>
      <h1 style={{ color: 'green' }}>GeeksforGeeks</h1>
      <h3>Next.js Functions: revalidateTag</h3>

      <form onSubmit={handleSubmit} style={{ marginTop: '20px' }}>
        <input
          type="text"
          value={postTitle}
          onChange={(e) => setPostTitle(e.target.value)}
          placeholder="Enter post title"
          style={{ padding: '10px', width: '300px' }}
        />
        <button type="submit" style={{ padding: '10px', marginLeft: '10px' }}>
          Add Post
        </button>
      </form>

      {message && <p style={{ marginTop: '20px', color: 'blue' }}>
        {message}
      </p>}
    </div>
  );
}
JavaScript
// src/app/api/revalidate/route.js

import { revalidateTag } from 'next/cache';

export async function GET(request) {
    const tag = request.nextUrl.searchParams.get('tag');

    if (tag) {
        revalidateTag(tag);
        return new Response(JSON.stringify({
            revalidated: true,
            now: Date.now()
        }), {
            headers: { 'Content-Type': 'application/json' },
        });
    } else {
        return new Response(JSON.stringify({
            revalidated: false,
            error: 'No tag provided'
        }), {
            headers: { 'Content-Type': 'application/json' },
        });
    }
}
JavaScript
// app/src/layout.js

import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

To run the Application open the terminal in the project folder and enter the following command:

npm run dev

Output:


Next Article
Article Tags :

Similar Reads