Clerk logo

Clerk Docs

Ctrl + K
Go to clerkstage.dev

Server Actions

Learn how to use Clerk with Server Actions

Clerk provides helpers to allow you to protect your Server Actions, fetch the current user and interact with the Clerk API.

Below are some examples of usage both in server components or client components

With server components

Protect your actions

1
import { auth } from '@clerk/nextjs';
2
3
export default function AddToCart() {
4
async function addItem(formData: FormData) {
5
'use server';
6
const { userId } = auth();
7
if (!userId) {
8
throw new Error('You must be signed in to add an item to your cart');
9
}
10
console.log('add item server action', formData);
11
}
12
13
return (
14
<form action={addItem}>
15
<input
16
value={'test'}
17
type='text'
18
name='name'
19
/>
20
<button type='submit'>Add to Cart</button>
21
</form>
22
);
23
}

Accessing the current user

Current user data is important for data enrichment and you can use the currentUser() helper to achieve this

1
import { currentUser } from '@clerk/nextjs';
2
3
export default function AddHobby() {
4
async function addHobby(formData: FormData) {
5
'use server';
6
const user = await currentUser();
7
if (!user) {
8
throw new Error('You must be signed in to use this feature');
9
}
10
const serverData = {
11
usersHobby: formData.get("hobby"),
12
userId: user.id,
13
profileImage: user.profileImageUrl
14
};
15
console.log('add item server action completed with user details ', serverData);
16
}
17
18
return (
19
<form action={addHobby}>
20
<input
21
value={'soccer'}
22
type='text'
23
name='hobby'
24
/>
25
<button type='submit'>Submit your hobby</button>
26
</form>
27
);
28
}

With client components

When using client components you need to make sure you use prop drilling to ensure that headers are available.

Protect your actions

Server Action Code

actions.ts
1
'use server'
2
import { auth } from '@clerk/nextjs';
3
4
export async function addItem(formData: FormData) {
5
const { userId } = auth();
6
if (!userId) {
7
throw new Error('You must be signed in to add an item to your cart');
8
}
9
console.log('add item server action', formData);
10
}

Server Page

page.tsx
1
import UI from "./UI";
2
import { addItem } from "./actions"
3
export default function Hobby() {
4
return (
5
<UI addItem={addItem} />
6
);
7
}

Client Component

ui.tsx
1
"use client"
2
3
export default function UI({ addItem }) {
4
return (
5
<form action={addItem}>
6
<input
7
value={'test'}
8
type='text'
9
name='name'
10
/>
11
<button type='submit'>Add to Cart</button>
12
</form>
13
)
14
}

Accessing the current user

Server Action Code

actions.ts
1
'use server'
2
import { currentUser } from "@clerk/nextjs";
3
4
export async function addHobby(formData: FormData) {
5
const user = await currentUser();
6
if (!user) {
7
throw new Error('You must be signed in to use this feature');
8
}
9
const serverData = {
10
usersHobby: formData.get("hobby"),
11
userId: user.id,
12
profileImage: user.profileImageUrl
13
};
14
console.log('add Hobby completed with user details ', serverData);
15
}

Server Page

page.tsx
1
import UI from "./ui";
2
import { addHobby } from "./actions"
3
export default function Hobby() {
4
return (
5
<UI addHobby={addHobby} />
6
);
7
}

Client Component

ui.tsx
1
"use client"
2
3
export default function UI({ addHobby }) {
4
5
return (
6
<form action={addHobby}>
7
<input
8
value={'soccer'}
9
type='text'
10
name='hobby'
11
/>
12
<button type='submit'>Submit your hobby</button>
13
</form>
14
)
15
}

Was this helpful?

Clerk © 2023