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
1import { auth } from '@clerk/nextjs';23export default function AddToCart() {4async function addItem(formData: FormData) {5'use server';6const { userId } = auth();7if (!userId) {8throw new Error('You must be signed in to add an item to your cart');9}10console.log('add item server action', formData);11}1213return (14<form action={addItem}>15<input16value={'test'}17type='text'18name='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
1import { currentUser } from '@clerk/nextjs';23export default function AddHobby() {4async function addHobby(formData: FormData) {5'use server';6const user = await currentUser();7if (!user) {8throw new Error('You must be signed in to use this feature');9}10const serverData = {11usersHobby: formData.get("hobby"),12userId: user.id,13profileImage: user.profileImageUrl14};15console.log('add item server action completed with user details ', serverData);16}1718return (19<form action={addHobby}>20<input21value={'soccer'}22type='text'23name='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.ts1'use server'2import { auth } from '@clerk/nextjs';34export async function addItem(formData: FormData) {5const { userId } = auth();6if (!userId) {7throw new Error('You must be signed in to add an item to your cart');8}9console.log('add item server action', formData);10}
Server Page
page.tsx1import UI from "./UI";2import { addItem } from "./actions"3export default function Hobby() {4return (5<UI addItem={addItem} />6);7}
Client Component
ui.tsx1"use client"23export default function UI({ addItem }) {4return (5<form action={addItem}>6<input7value={'test'}8type='text'9name='name'10/>11<button type='submit'>Add to Cart</button>12</form>13)14}
Accessing the current user
Server Action Code
actions.ts1'use server'2import { currentUser } from "@clerk/nextjs";34export async function addHobby(formData: FormData) {5const user = await currentUser();6if (!user) {7throw new Error('You must be signed in to use this feature');8}9const serverData = {10usersHobby: formData.get("hobby"),11userId: user.id,12profileImage: user.profileImageUrl13};14console.log('add Hobby completed with user details ', serverData);15}
Server Page
page.tsx1import UI from "./ui";2import { addHobby } from "./actions"3export default function Hobby() {4return (5<UI addHobby={addHobby} />6);7}
Client Component
ui.tsx1"use client"23export default function UI({ addHobby }) {45return (6<form action={addHobby}>7<input8value={'soccer'}9type='text'10name='hobby'11/>12<button type='submit'>Submit your hobby</button>13</form>14)15}