Day 17 β Revalidating Data: Freshness on Demand
π§ Day 17 β Revalidating Data: Freshness on Demand
Zero to Hero β Hands-on Next.js Tutorial
Next.js is aggressive about caching. If you fetch data in a Server Component, Next.js might cache it indefinitely. When you perform a Server Action (e.g., adding a new To-Do item), the UI wonβt update unless you tell Next.js: βThe data has changed!β
π¦ 1. revalidatePath
This is the most common way to refresh data. It purges the cache for a specific URL path.
'use server';
import { revalidatePath } from 'next/cache';
export async function createTodo(formData: FormData) {
await db.todo.create({ ... });
// "Hey Next.js, throw away the cached HTML for /todos"
// "The next time someone visits, regenerate it."
revalidatePath('/todos');
}
revalidatePath('/todos')-> Refreshes only that page.revalidatePath('/', 'layout')-> Refreshes the root and everything inside it.
π© 2. revalidateTag
Path-based revalidation is simple, but what if the same data (e.g., a list of products) is used on the Home Page, the Shop Page, AND the Admin Dashboard?
Youβd have to call revalidatePath 3 times. π«
Better: Use Cache Tags.
-
Tag the fetch:
// getProducts.ts fetch('https://api/products', { next: { tags: ['products'] } }); -
Invalidate the tag:
// updateProduct.ts ('use server') import { revalidateTag } from 'next/cache'; export async function updateProduct() { await db.update(...) // Purge EVERY fetch request marked with 'products' // No matter which page it is on! revalidateTag('products'); }
π§ 3. Optimistic Updates (useOptimistic)
Revalidation takes time (Server Roundtrip).
To make the UI feel instant, use useOptimistic.
'use client';
import { useOptimistic } from 'react';
export function TodoList({ todos }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, newTodo]
);
return (
<div>
{optimisticTodos.map(t => <div key={t.id}>{t.title}</div>)}
<form action={async (formData) => {
const title = formData.get('title');
// 1. Show the new item IMMEDIATELY (Mock ID)
addOptimisticTodo({ id: Math.random(), title });
// 2. Actually save to server (Background)
await createTodo(formData);
}}>
<button>Add</button>
</form>
</div>
);
}
π§ͺ Challenge: Day 17
- Create a list of items fetched with a tag:
fetch('...', { next: { tags: ['items'] } }). - Create a button βAdd Random Itemβ.
- In the Server Action, add the item and call
revalidateTag('items'). - Observe closely: The page should automatically reload the list without a full browser refresh!
See you tomorrow for Cookies & Headers! πͺ