Skip to content

Commit 2718661

Browse files
icyJosephdelbaoliveiravercel[bot]hanzala-sohrab
authored
Backport/docs fixes (#89031)
A handful of PRs to sync w/ next patch release --------- Co-authored-by: Delba de Oliveira <[email protected]> Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> Co-authored-by: Hanzala Sohrab <[email protected]>
1 parent 5333625 commit 2718661

File tree

13 files changed

+517
-30
lines changed

13 files changed

+517
-30
lines changed

docs/01-app/01-getting-started/05-server-and-client-components.mdx

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,191 @@ Your Server Component will now be able to directly render your provider, and all
412412

413413
> **Good to know**: You should render providers as deep as possible in the tree – notice how `ThemeProvider` only wraps `{children}` instead of the entire `<html>` document. This makes it easier for Next.js to optimize the static parts of your Server Components.
414414
415+
### Sharing data with context and React.cache
416+
417+
You can share fetched data across both Server and Client Components by combining [`React.cache`](https://react.dev/reference/react/cache) with context providers.
418+
419+
Create a cached function that fetches data:
420+
421+
```ts filename="app/lib/user.ts" switcher
422+
import { cache } from 'react'
423+
424+
export const getUser = cache(async () => {
425+
const res = await fetch('https://api.example.com/user')
426+
return res.json()
427+
})
428+
```
429+
430+
```js filename="app/lib/user.js" switcher
431+
import { cache } from 'react'
432+
433+
export const getUser = cache(async () => {
434+
const res = await fetch('https://api.example.com/user')
435+
return res.json()
436+
})
437+
```
438+
439+
Create a context provider that stores the promise:
440+
441+
```tsx filename="app/user-provider.tsx" switcher
442+
'use client'
443+
444+
import { createContext } from 'react'
445+
446+
type User = {
447+
id: string
448+
name: string
449+
}
450+
451+
export const UserContext = createContext<Promise<User> | null>(null)
452+
453+
export default function UserProvider({
454+
children,
455+
userPromise,
456+
}: {
457+
children: React.ReactNode
458+
userPromise: Promise<User>
459+
}) {
460+
return <UserContext value={userPromise}>{children}</UserContext>
461+
}
462+
```
463+
464+
```jsx filename="app/user-provider.js" switcher
465+
'use client'
466+
467+
import { createContext } from 'react'
468+
469+
export const UserContext = createContext(null)
470+
471+
export default function UserProvider({ children, userPromise }) {
472+
return <UserContext value={userPromise}>{children}</UserContext>
473+
}
474+
```
475+
476+
In a layout, pass the promise to the provider without awaiting:
477+
478+
```tsx filename="app/layout.tsx" switcher
479+
import UserProvider from './user-provider'
480+
import { getUser } from './lib/user'
481+
482+
export default function RootLayout({
483+
children,
484+
}: {
485+
children: React.ReactNode
486+
}) {
487+
const userPromise = getUser() // Don't await
488+
489+
return (
490+
<html>
491+
<body>
492+
<UserProvider userPromise={userPromise}>{children}</UserProvider>
493+
</body>
494+
</html>
495+
)
496+
}
497+
```
498+
499+
```jsx filename="app/layout.js" switcher
500+
import UserProvider from './user-provider'
501+
import { getUser } from './lib/user'
502+
503+
export default function RootLayout({ children }) {
504+
const userPromise = getUser() // Don't await
505+
506+
return (
507+
<html>
508+
<body>
509+
<UserProvider userPromise={userPromise}>{children}</UserProvider>
510+
</body>
511+
</html>
512+
)
513+
}
514+
```
515+
516+
Client Components use [`use()`](https://react.dev/reference/react/use) to resolve the promise from context, wrapped in `<Suspense>` for fallback UI:
517+
518+
```tsx filename="app/ui/profile.tsx" switcher
519+
'use client'
520+
521+
import { use, useContext } from 'react'
522+
import { UserContext } from '../user-provider'
523+
524+
export function Profile() {
525+
const userPromise = useContext(UserContext)
526+
if (!userPromise) {
527+
throw new Error('useContext must be used within a UserProvider')
528+
}
529+
const user = use(userPromise)
530+
return <p>Welcome, {user.name}</p>
531+
}
532+
```
533+
534+
```jsx filename="app/ui/profile.js" switcher
535+
'use client'
536+
537+
import { use, useContext } from 'react'
538+
import { UserContext } from '../user-provider'
539+
540+
export function Profile() {
541+
const userPromise = useContext(UserContext)
542+
if (!userPromise) {
543+
throw new Error('useContext must be used within a UserProvider')
544+
}
545+
const user = use(userPromise)
546+
return <p>Welcome, {user.name}</p>
547+
}
548+
```
549+
550+
```tsx filename="app/page.tsx" switcher
551+
import { Suspense } from 'react'
552+
import { Profile } from './ui/profile'
553+
554+
export default function Page() {
555+
return (
556+
<Suspense fallback={<div>Loading profile...</div>}>
557+
<Profile />
558+
</Suspense>
559+
)
560+
}
561+
```
562+
563+
```jsx filename="app/page.js" switcher
564+
import { Suspense } from 'react'
565+
import { Profile } from './ui/profile'
566+
567+
export default function Page() {
568+
return (
569+
<Suspense fallback={<div>Loading profile...</div>}>
570+
<Profile />
571+
</Suspense>
572+
)
573+
}
574+
```
575+
576+
Server Components can also call `getUser()` directly:
577+
578+
```tsx filename="app/dashboard/page.tsx" switcher
579+
import { getUser } from '../lib/user'
580+
581+
export default async function DashboardPage() {
582+
const user = await getUser() // Cached - same request, no duplicate fetch
583+
return <h1>Dashboard for {user.name}</h1>
584+
}
585+
```
586+
587+
```jsx filename="app/dashboard/page.js" switcher
588+
import { getUser } from '../lib/user'
589+
590+
export default async function DashboardPage() {
591+
const user = await getUser() // Cached - same request, no duplicate fetch
592+
return <h1>Dashboard for {user.name}</h1>
593+
}
594+
```
595+
596+
Since `getUser` is wrapped with `React.cache`, multiple calls within the same request return the same memoized result, whether called directly in Server Components or resolved via context in Client Components.
597+
598+
> **Good to know**: `React.cache` is scoped to the current request only. Each request gets its own memoization scope with no sharing between requests.
599+
415600
### Third-party components
416601

417602
When using a third-party component that relies on client-only features, you can wrap it in a Client Component to ensure it works as expected.

docs/01-app/01-getting-started/06-cache-components.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ Use [`connection()`](/docs/app/api-reference/functions/connection) if you need t
194194

195195
> **Good to know**: Runtime data cannot be cached with `use cache` because it requires request context. Components that access runtime APIs must always be wrapped in `<Suspense>`. However, you can extract values from runtime data and pass them as arguments to cached functions. See the [with runtime data](#with-runtime-data) section for an example.
196196
197+
One approach for reading runtime data like cookies without blocking the static shell is to pass a promise to a client context provider. See [Sharing data with context and React.cache](/docs/app/getting-started/server-and-client-components#sharing-data-with-context-and-reactcache) for an example.
198+
199+
> **Good to know:** `React.cache` operates in an isolated scope inside `use cache` boundaries. See [React.cache isolation](/docs/app/api-reference/directives/use-cache#reactcache-isolation) for more information.
200+
197201
### Non-deterministic operations
198202

199203
Operations like `Math.random()`, `Date.now()`, or `crypto.randomUUID()` produce different values each time they execute. To ensure these run at request time (generating unique values per request), Cache Components requires you to explicitly signal this intent by calling these operations after dynamic or runtime data access.

docs/01-app/01-getting-started/08-updating-data.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Updating Data
3-
description: Learn how to mutate data using Server Functions.
3+
description: Learn how to mutate data using Server Functions and Server Actions in Next.js.
44
related:
55
title: API Reference
66
description: Learn more about the features mentioned in this page by reading the API Reference.
@@ -18,6 +18,8 @@ A **Server Function** is an asynchronous function that runs on the server. They
1818

1919
In an `action` or mutation context, they are also called **Server Actions**.
2020

21+
> **Good to know:** A Server Action is a Server Function used in a specific way (for handling form submissions and mutations). Server Function is the broader term.
22+
2123
By convention, a Server Action is an async function used with [`startTransition`](https://react.dev/reference/react/startTransition). This happens automatically when the function is:
2224

2325
- Passed to a `<form>` using the `action` prop.
@@ -427,7 +429,7 @@ Calling `redirect` [throws](/docs/app/api-reference/functions/redirect#behavior)
427429

428430
You can `get`, `set`, and `delete` cookies inside a Server Action using the [`cookies`](/docs/app/api-reference/functions/cookies) API.
429431

430-
When you [set or delete](/docs/app/api-reference/functions/cookies#understanding-cookie-behavior-in-server-actions) a cookie in a Server Action, Next.js re-renders the current page and its layouts on the server so the **UI reflects the new cookie value**.
432+
When you [set or delete](/docs/app/api-reference/functions/cookies#understanding-cookie-behavior-in-server-functions) a cookie in a Server Action, Next.js re-renders the current page and its layouts on the server so the **UI reflects the new cookie value**.
431433

432434
> **Good to know**: The server update applies to the current React tree, re-rendering, mounting, or unmounting components, as needed. Client state is preserved for re-rendered components, and effects re-run if their dependencies changed.
433435

docs/01-app/02-guides/redirecting.mdx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ There are a few ways you can handle redirects in Next.js. This page will go thro
1414

1515
<AppOnly>
1616

17-
| API | Purpose | Where | Status Code |
18-
| ------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | -------------------------------------- |
19-
| [`redirect`](#redirect-function) | Redirect user after a mutation or event | Server Components, Server Actions, Route Handlers | 307 (Temporary) or 303 (Server Action) |
20-
| [`permanentRedirect`](#permanentredirect-function) | Redirect user after a mutation or event | Server Components, Server Actions, Route Handlers | 308 (Permanent) |
21-
| [`useRouter`](#userouter-hook) | Perform a client-side navigation | Event Handlers in Client Components | N/A |
22-
| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | Redirect an incoming request based on a path | `next.config.js` file | 307 (Temporary) or 308 (Permanent) |
23-
| [`NextResponse.redirect`](#nextresponseredirect-in-proxy) | Redirect an incoming request based on a condition | Proxy | Any |
17+
| API | Purpose | Where | Status Code |
18+
| ------------------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------- | -------------------------------------- |
19+
| [`redirect`](#redirect-function) | Redirect user after a mutation or event | Server Components, Server Functions, Route Handlers | 307 (Temporary) or 303 (Server Action) |
20+
| [`permanentRedirect`](#permanentredirect-function) | Redirect user after a mutation or event | Server Components, Server Functions, Route Handlers | 308 (Permanent) |
21+
| [`useRouter`](#userouter-hook) | Perform a client-side navigation | Event Handlers in Client Components | N/A |
22+
| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | Redirect an incoming request based on a path | `next.config.js` file | 307 (Temporary) or 308 (Permanent) |
23+
| [`NextResponse.redirect`](#nextresponseredirect-in-proxy) | Redirect an incoming request based on a condition | Proxy | Any |
2424

2525
</AppOnly>
2626

@@ -38,7 +38,7 @@ There are a few ways you can handle redirects in Next.js. This page will go thro
3838

3939
## `redirect` function
4040

41-
The `redirect` function allows you to redirect the user to another URL. You can call `redirect` in [Server Components](/docs/app/getting-started/server-and-client-components), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Server Actions](/docs/app/getting-started/updating-data).
41+
The `redirect` function allows you to redirect the user to another URL. You can call `redirect` in [Server Components](/docs/app/getting-started/server-and-client-components), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Server Functions](/docs/app/getting-started/updating-data).
4242

4343
`redirect` is often used after a mutation or event. For example, creating a post:
4444

@@ -90,7 +90,7 @@ See the [`redirect` API reference](/docs/app/api-reference/functions/redirect) f
9090

9191
## `permanentRedirect` function
9292

93-
The `permanentRedirect` function allows you to **permanently** redirect the user to another URL. You can call `permanentRedirect` in [Server Components](/docs/app/getting-started/server-and-client-components), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Server Actions](/docs/app/getting-started/updating-data).
93+
The `permanentRedirect` function allows you to **permanently** redirect the user to another URL. You can call `permanentRedirect` in [Server Components](/docs/app/getting-started/server-and-client-components), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Server Functions](/docs/app/getting-started/updating-data).
9494

9595
`permanentRedirect` is often used after a mutation or event that changes an entity's canonical URL, such as updating a user's profile URL after they change their username:
9696

docs/01-app/02-guides/scripts.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ Refer to the [`next/script`](/docs/app/api-reference/components/script#strategy)
127127

128128
> **Warning:** The `worker` strategy is not yet stable and does not yet work with the App Router. Use with caution.
129129
130-
Scripts that use the `worker` strategy are offloaded and executed in a web worker with [Partytown](https://partytown.builder.io/). This can improve the performance of your site by dedicating the main thread to the rest of your application code.
130+
Scripts that use the `worker` strategy are offloaded and executed in a web worker with [Partytown](https://partytown.qwik.dev/). This can improve the performance of your site by dedicating the main thread to the rest of your application code.
131131

132132
This strategy is still experimental and can only be used if the `nextScriptWorkers` flag is enabled in `next.config.js`:
133133

@@ -145,7 +145,7 @@ Then, run `next` (normally `npm run dev` or `yarn dev`) and Next.js will guide y
145145
npm run dev
146146
```
147147

148-
You'll see instructions like these: Please install Partytown by running `npm install @builder.io/partytown`
148+
You'll see instructions like these: Please install Partytown by running `npm install @qwik.dev/partytown`
149149

150150
Once setup is complete, defining `strategy="worker"` will automatically instantiate Partytown in your application and offload the script to a web worker.
151151

@@ -173,7 +173,7 @@ export default function Home() {
173173
}
174174
```
175175

176-
There are a number of trade-offs that need to be considered when loading a third-party script in a web worker. Please see Partytown's [tradeoffs](https://partytown.builder.io/trade-offs) documentation for more information.
176+
There are a number of trade-offs that need to be considered when loading a third-party script in a web worker. Please see Partytown's [tradeoffs](https://partytown.qwik.dev/trade-offs) documentation for more information.
177177

178178
<PagesOnly>
179179

@@ -218,7 +218,7 @@ In order to modify Partytown's configuration, the following conditions must be m
218218

219219
> **Note**: If you are using an [asset prefix](/docs/pages/api-reference/config/next-config-js/assetPrefix) and would like to modify Partytown's default configuration, you must include it as part of the `lib` path.
220220
221-
Take a look at Partytown's [configuration options](https://partytown.builder.io/configuration) to see the full list of other properties that can be added.
221+
Take a look at Partytown's [configuration options](https://partytown.qwik.dev/configuration) to see the full list of other properties that can be added.
222222

223223
</PagesOnly>
224224

docs/01-app/03-api-reference/01-directives/use-cache.mdx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ async function CachedForm({ action }: { action: () => Promise<void> }) {
189189

190190
## Constraints
191191

192+
Cached functions execute in an isolated environment. The following constraints ensure cache behavior remains predictable and secure.
193+
194+
### Runtime APIs
195+
192196
Cached functions and components **cannot** directly access runtime APIs like `cookies()`, `headers()`, or `searchParams`. Instead, read these values outside the cached scope and pass them as arguments.
193197

194198
### Runtime caching considerations
@@ -206,6 +210,34 @@ If the default in-memory cache isn't enough, consider **[`use cache: remote`](/d
206210

207211
Very rarely, for compliance requirements or when you can't refactor your code to pass runtime data as arguments to a `use cache` scope, you might need [`use cache: private`](/docs/app/api-reference/directives/use-cache-private).
208212

213+
### React.cache isolation
214+
215+
[`React.cache`](https://react.dev/reference/react/cache) operates in an isolated scope inside `use cache` boundaries. Values stored via `React.cache` outside a `use cache` function are not visible inside it.
216+
217+
This means you cannot use `React.cache` to pass data into a `use cache` scope:
218+
219+
```tsx
220+
import { cache } from 'react'
221+
222+
const store = cache(() => ({ current: null as string | null }))
223+
224+
function Parent() {
225+
const shared = store()
226+
shared.current = 'value from parent'
227+
return <Child />
228+
}
229+
230+
async function Child() {
231+
'use cache'
232+
const shared = store()
233+
// shared.current is null, not 'value from parent'
234+
// use cache has its own isolated React.cache scope
235+
return <div>{shared.current}</div>
236+
}
237+
```
238+
239+
This isolation ensures cached functions have predictable, self-contained behavior. To pass data into a `use cache` scope, use function arguments instead.
240+
209241
## `use cache` at runtime
210242

211243
On the **server**, cache entries are stored in-memory and respect the `revalidate` and `expire` times from your `cacheLife` configuration. You can customize the cache storage by configuring [`cacheHandlers`](/docs/app/api-reference/config/next-config-js/cacheHandlers) in your `next.config.js` file.

docs/01-app/03-api-reference/04-functions/after.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: API Reference for the after function.
55

66
`after` allows you to schedule work to be executed after a response (or prerender) is finished. This is useful for tasks and other side effects that should not block the response, such as logging and analytics.
77

8-
It can be used in [Server Components](/docs/app/getting-started/server-and-client-components) (including [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata)), [Server Actions](/docs/app/getting-started/updating-data), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Proxy](/docs/app/api-reference/file-conventions/proxy).
8+
It can be used in [Server Components](/docs/app/getting-started/server-and-client-components) (including [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata)), [Server Functions](/docs/app/getting-started/updating-data), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Proxy](/docs/app/api-reference/file-conventions/proxy).
99

1010
The function accepts a callback that will be executed after the response (or prerender) is finished:
1111

@@ -59,7 +59,7 @@ export default function Layout({ children }) {
5959

6060
### With request APIs
6161

62-
You can use request APIs such as [`cookies`](/docs/app/api-reference/functions/cookies) and [`headers`](/docs/app/api-reference/functions/headers) inside `after` in [Server Actions](/docs/app/getting-started/updating-data) and [Route Handlers](/docs/app/api-reference/file-conventions/route). This is useful for logging activity after a mutation. For example:
62+
You can use request APIs such as [`cookies`](/docs/app/api-reference/functions/cookies) and [`headers`](/docs/app/api-reference/functions/headers) inside `after` in [Server Functions](/docs/app/getting-started/updating-data) and [Route Handlers](/docs/app/api-reference/file-conventions/route). This is useful for logging activity after a mutation. For example:
6363

6464
```ts filename="app/api/route.ts" highlight={2,7-9} switcher
6565
import { after } from 'next/server'

0 commit comments

Comments
 (0)