new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Next.js App Router · all subjects

data-fetching-caching/patterns

20 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Sequential data fetching

Sequential data fetching happens when one request depends on data from another. For example, when <Playlists> needs an artistID from getArtist() before it can fetch playlists. The page waits for the first request to complete before the second can start.

Sequential data fetching with Suspense

Example of sequential data fetching: await the first request (getArtist), pass its result to a Server Component wrapped in <Suspense>, and that component fetches the dependent data (getArtistPlaylists). The fallback is shown while the dependent component loads.

Parallel data fetching with Promise.all

Parallel data fetching happens when data requests in a route are eagerly initiated and start at the same time. Start multiple requests by calling fetch functions, then await them with Promise.all(). Requests begin as soon as fetch is called, not when you await.

Parallel data fetching example

Call getArtist(username) and getAlbums(username) without await to start both requests immediately. Then use const [artist, albums] = await Promise.all([artistData, albumsData]) to wait for both to resolve.

Promise.allSettled for error handling

If one request fails when using Promise.all, the entire operation will fail. Use Promise.allSettled() method instead to handle individual request failures without failing the entire operation.

refresh() function revalidates current page after mutation

After a mutation, call refresh() from 'next/cache' in a Server Action to refresh the client router and ensure the UI reflects the latest state. The refresh() function does not revalidate tagged data; use updateTag() or revalidateTag() instead for tagged data.

revalidatePath and revalidateTag after mutations

After performing a mutation, call revalidatePath() or revalidateTag() within the Server Function to revalidate the Next.js cache and show updated data.

Example: Revalidate cache after mutation

This example shows how to use revalidatePath to refresh cached data after a mutation: ```ts 'use server' import { auth } from '@/lib/auth' import { revalidatePath } from 'next/cache' export async function createPost(formData: FormData) { const session = await auth() if (!session?.user) { throw new Error('Unauthorized') } // Mutate data // ... revalidatePath('/posts') } ```

Memoizing data requests with React cache to avoid duplicates

When the same data is needed for both metadata and page rendering, use React's cache function to memoize the return value and ensure the data is fetched only once. This prevents duplicate requests when both generateMetadata and the page component need the same data.

Passing runtime values to cached functions

You can extract values from runtime APIs and pass them as arguments to cached functions. This allows the cached function to be included in the prefetched content. Example: a non-cached component reads runtime data like `session` from cookies, then passes it to a cached component that receives it as a prop, making the sessionId part of the cache key.

Passing runtime values example

Example: `async function ProfileContent() { const session = (await cookies()).get('session')?.value; return <CachedContent sessionId={session} />; } async function CachedContent({ sessionId }: { sessionId: string }) { 'use cache'; const data = await fetchUserData(sessionId); return <div>{data}</div>; }`

Reading local resources at module scope

Some asynchronous APIs read local resources that don't depend on the incoming request, such as fonts or configuration files. When those resources are expected to be the same for every request, read them once at module scope instead of during rendering to avoid treating them as uncached data.

App Shell with unknown dynamic params

When dynamic params aren't known at build time, the reusable, URL-independent version is the App Shell: the same static shell with the param-specific parts left behind their fallbacks. Incremental Static Regeneration fills in the concrete versions after the first visit.

Incremental Static Regeneration with generateStaticParams

In a route with dynamic param segments, `generateStaticParams` prerenders the URLs you list at build time. Any other URL is served the App Shell instantly, then upgraded in the background with its now-known params and cached for the next visitor.

Dynamic rendering definition

Dynamic rendering occurs when a component is rendered at request time rather than build time. A component becomes dynamic when it uses Request-time APIs.

Incremental Static Regeneration (ISR) definition

ISR is a technique that allows you to update static content without rebuilding the entire site. It enables you to use static generation on a per-page basis while revalidating pages in the background as traffic comes in. In Next.js, ISR is also known as Revalidation.

Prerendering definition

Prerendering occurs when a component is rendered at build time or in the background during revalidation. The result is HTML and RSC Payload, which can be cached and served from a CDN. Prerendering is the default for components that don't use Request-time APIs.

Request-time APIs list

Request-time APIs are functions that access request-specific data, causing a component to opt into dynamic rendering. These include: cookies() to access request cookies, headers() to access request headers, searchParams to access URL query parameters, and draftMode() to enable or check draft mode.

Optimistic update should restore previous browser value if write fails

An optimistic update should restore the previous browser value if the write fails. If the server read is not cached, there is no server tag to invalidate.

Invalidate cached server read after mutation to enable fresh data on next render

After a mutation, invalidate any cached server read that provided the initial data so the next render can read a fresh value.

Give your agent this brain