--- name: safe-action-hooks description: Use when executing next-safe-action actions from React client components -- useAction, useOptimisticAction, handling status/callbacks (onSuccess/onError/onSettled), execute vs executeAsync, or optimistic UI updates --- # next-safe-action React Hooks ## Import ```ts // All hooks import { useAction, useOptimisticAction, useStateAction } from "next-safe-action/hooks"; // Backward-compatible re-export (same useStateAction hook) import { useStateAction } from "next-safe-action/stateful-hooks"; ``` ## useAction — Quick Start ```tsx "use client"; import { useAction } from "next-safe-action/hooks"; import { createUser } from "@/app/actions"; export function CreateUserForm() { const { execute, result, status, isExecuting, isPending } = useAction(createUser, { onSuccess: ({ data }) => { console.log("User created:", data); }, onError: ({ error }) => { console.error("Failed:", error.serverError); }, }); return (
{ e.preventDefault(); const formData = new FormData(e.currentTarget); execute({ name: formData.get("name") as string }); }}> {result.serverError &&

{result.serverError}

} {result.data &&

Created: {result.data.id}

}
); } ``` ## useOptimisticAction — Quick Start ```tsx "use client"; import { useOptimisticAction } from "next-safe-action/hooks"; import { toggleTodo } from "@/app/actions"; export function TodoItem({ todo }: { todo: Todo }) { const { execute, optimisticState } = useOptimisticAction(toggleTodo, { currentState: todo, updateFn: (state, input) => ({ ...state, completed: !state.completed, }), }); return ( ); } ``` ## useStateAction — Quick Start ```tsx "use client"; import { useStateAction } from "next-safe-action/hooks"; import { submitFeedback } from "@/app/actions"; export function FeedbackForm() { const { formAction, result, isPending, hasSucceeded } = useStateAction(submitFeedback, { onSuccess: ({ data }) => { console.log("Submitted:", data); }, onError: ({ error }) => { console.error("Failed:", error.serverError); }, }); return (