next-safe-action
Guides

Executing actions

There are four ways to execute a safe action from a Client Component. Each approach serves different needs:

Three execution methods: Direct Call, useAction, Form Action

Comparison

Given the same action:

src/app/actions.ts
"use server";

import { z } from "zod";
import { actionClient } from "@/lib/safe-action";

export const greetUser = actionClient
	.inputSchema(z.object({ name: z.string() }))
	.action(async ({ parsedInput }) => {
		return { greeting: `Hello, ${parsedInput.name}!` };
	});

Here's how each method calls it:

src/app/page.tsx
"use client";

import { greetUser } from "./actions";

export default function Page() {
	const handleClick = async () => {
		const result = await greetUser({ name: "Alice" });

		if (result.data) {
			alert(result.data.greeting);
		}
	};

	return <button onClick={handleClick}>Greet</button>;
}

Use when: You need a simple one-off call, or you're calling from a Server Component or event handler where you don't need reactive UI updates.

Which method should I use?

NeedMethod
Simple call, no loading UIDirect call
Loading states, callbacks, reactive resultuseAction hook
Forms with callbacks, status, and prevResultuseStateAction hook
Optimistic UI updatesuseOptimisticAction hook
Optimistic UI updates that must queue, not raceuseOptimisticStateAction hook
Progressive enhancement / no-JS formsuseActionState (React)
Server Component calling an actionDirect call

What's next?

On this page