Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Recommend inline use server and update examples #77770

Merged
merged 2 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 32 additions & 28 deletions docs/01-app/01-getting-started/07-updating-data.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,34 @@ You can update data in Next.js using React's [Server Functions](https://react.de

## Creating Server Functions

A Server Function can be defined by using the [`use server`](https://react.dev/reference/rsc/use-server) directive. You can place the directive at the top of an **asynchronous** function to mark the function as a Server Function, or at the top of a separate file to mark all exports of that file. We recommend using a separate file in most instances.
A Server Function can be defined by using the [`use server`](https://react.dev/reference/rsc/use-server) directive. You can place the directive in an **asynchronous** function to mark the function as a Server Function.

```ts filename="app/lib/actions.ts" switcher
'use server'

export async function createPost(formData: FormData) {}
export async function createPost(formData: FormData) {
'use server'
// Update data
}

export async function deletePost(formData: FormData) {}
export async function deletePost(formData: FormData) {
'use server'
// Update data
}
```

```js filename="app/lib/actions.js" switcher
'use server'

export async function createPost(formData) {}
export async function createPost(formData) {
'use server'
// Update data
}

export async function deletePost(formData) {}
export async function deletePost(formData) {
'use server'
// Update data
}
```

> You can also add `use server` at the top of a file to mark all exports of that file as Server Functions. However, this can lead to functions being marked as Server Functions when they are not intended to be used as such. We recommend scoping `use server` to the function level instead as shown above.

### Server Components

Server Functions can be inlined in Server Components by adding the `"use server"` directive to the top of the function body:
Expand Down Expand Up @@ -65,18 +75,18 @@ export default function Page() {

### Client Components

It's not possible to define Server Functions in Client Components. However, you can invoke them in Client Components by importing them from a file that has the `"use server"` directive at the top of it:
It's not possible to define Server Functions in Client Components. However, you can invoke them in Client Components by placing the functions in a separate file and importing them:

```ts filename="app/actions.ts" switcher
'use server'

export async function createPost() {}
export async function createPost() {
'use server'
}
```

```js filename="app/actions.js" switcher
'use server'

export async function createPost() {}
export async function createPost() {
'use server'
}
```

```tsx filename="app/ui/button.tsx" switcher
Expand Down Expand Up @@ -141,9 +151,8 @@ export function Form() {
```

```ts filename="app/actions.ts" switcher
'use server'

export async function createPost(formData: FormData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')

Expand All @@ -153,9 +162,8 @@ export async function createPost(formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

export async function createPost(formData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')

Expand Down Expand Up @@ -265,11 +273,10 @@ export function Button() {
After performing an update, you can revalidate the Next.js cache and show the updated data by calling [`revalidatePath`](/docs/app/api-reference/functions/revalidatePath) or [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) within the Server Function:

```ts filename="app/lib/actions.ts" switcher
'use server'

import { revalidatePath } from 'next/cache'

export async function createPost(formData: FormData) {
'use server'
// Update data
// ...

Expand All @@ -278,11 +285,10 @@ export async function createPost(formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

import { revalidatePath } from 'next/cache'

export async function createPost(formData) {
'use server'
// Update data
// ...
revalidatePath('/posts')
Expand All @@ -294,11 +300,10 @@ export async function createPost(formData) {
You may want to redirect the user to a different page after performing an update. You can do this by calling [`redirect`](/docs/app/api-reference/functions/redirect) within the Server Function:

```ts filename="app/lib/actions.ts" switcher
'use server'

import { redirect } from 'next/navigation'

export async function createPost(formData: FormData) {
'use server'
// Update data
// ...

Expand All @@ -307,11 +312,10 @@ export async function createPost(formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

import { redirect } from 'next/navigation'

export async function createPost(formData) {
'use server'
// Update data
// ...

Expand Down
6 changes: 2 additions & 4 deletions docs/01-app/01-getting-started/08-error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ Expected errors are those that can occur during the normal operation of the appl
You can use the [`useActionState`](https://react.dev/reference/react/useActionState) hook to manage the state of [Server Functions](https://react.dev/reference/rsc/server-functions) and handle expected errors. Avoid using `try`/`catch` blocks for expected errors. Instead, you can model expected errors as return values, not as thrown exceptions.

```ts filename="app/actions.ts" switcher
'use server'

export async function createPost(prevState: any, formData: FormData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')

Expand All @@ -42,9 +41,8 @@ export async function createPost(prevState: any, formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

export async function createPost(prevState, formData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ Expected errors are those that can occur during the normal operation of the appl
Use the `useActionState` hook to manage the state of Server Actions, including handling errors. This approach avoids `try`/`catch` blocks for expected errors, which should be modeled as return values rather than thrown exceptions.

```ts filename="app/actions.ts" switcher
'use server'

import { redirect } from 'next/navigation'

export async function createUser(prevState: any, formData: FormData) {
'use server'
const res = await fetch('https://...')
const json = await res.json()

Expand All @@ -37,11 +36,10 @@ export async function createUser(prevState: any, formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

import { redirect } from 'next/navigation'

export async function createUser(prevState, formData) {
'use server'
const res = await fetch('https://...')
const json = await res.json()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ The `redirect` function allows you to redirect the user to another URL. You can
`redirect` is often used after a mutation or event. For example, creating a post:

```ts filename="app/actions.ts" switcher
'use server'

import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function createPost(id: string) {
'use server'
try {
// Call database
} catch (error) {
Expand All @@ -60,12 +59,11 @@ export async function createPost(id: string) {
```

```js filename="app/actions.js" switcher
'use server'

import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function createPost(id) {
'use server'
try {
// Call database
} catch (error) {
Expand Down Expand Up @@ -94,12 +92,11 @@ The `permanentRedirect` function allows you to **permanently** redirect the user
`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:

```ts filename="app/actions.ts" switcher
'use server'

import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'

export async function updateUsername(username: string, formData: FormData) {
'use server'
try {
// Call database
} catch (error) {
Expand All @@ -112,12 +109,11 @@ export async function updateUsername(username: string, formData: FormData) {
```

```js filename="app/actions.js" switcher
'use server'

import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'

export async function updateUsername(username, formData) {
'use server'
try {
// Call database
} catch (error) {
Expand Down
Loading
Loading