createServerAction
The createServerAction
function is returned by createClient
and is used to define individual server actions in your application.
Each server action:
- Validates the input using a Zod schema
- Automatically applies shared middleware, context, and error handling defined in
createClient
- Accepts optional
options
likeclear
to reset form state on error - Returns a structured
Response
object compatible withuseActionState
on the client
Basic Usage
app/_lib/actions/sign-in.ts
"use server";
import { z } from "zod";
import { createServerAction } from "../utils/server-actions";
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export const signIn = createServerAction<typeof schema>(
schema,
async (values) => {
// Your server-side logic here
return { ok: true };
}
);
Function Signature
function createServerAction<S extends ZodSchema, R = object>(
schema: S,
handler: (values: z.infer<S>, context: C) => Promise<Response<S, R>>,
options?: CreateServerActionOptions
): (
prev: Response<S, R>,
data: FormData
) => Promise<Response<S, R>>;
Parameters
schema
: A Zod schema used to validate the incoming form data.handler
: A function that receives the validated values and the context (if defined). It must return aResponse
object.options
(optional):clear?: boolean
– Iftrue
(default), submitted form values will be cleared on error. Set tofalse
to preserve user input after validation or middleware failure.
Return Type
Each server action returns a Response
object:
export type Response<S extends ZodSchema, R = object> = {
ok: boolean;
message?: string | { title: string; description: string };
errors?: { [K in keyof z.infer<S>]?: string[] };
values?: Partial<z.infer<S>>;
response?: R;
};
Behavior
- If
ok: true
, the action was successful. You may optionally return aresponse
object with any type-safe data. - If
ok: false
, the response may contain: - A general
message
(string or object with title/description) errors
for field-level validation (from Zod)values
containing submitted form data, unlessclear: true
(default) was applied
Examples
Custom Response
Return structured data when the action succeeds:
export const signIn = createServerAction<typeof schema, { url: string }>(
schema,
async (values) => {
return { ok: true, response: { url: "https://example.com/dashboard" } };
},
);
The response
property is strongly typed as { url: string }
.
Empty Response
If you don’t need to return additional data:
export const signIn = createServerAction<typeof schema>(
schema,
async (values) => {
return { ok: true };
},
);
Form-Level Error
Return a general message
when submission fails:
export const signIn = createServerAction<typeof schema>(
schema,
async (values) => {
return { ok: false, message: "Invalid credentials" };
},
);
Preserve Form Values on Error
Use clear: false
to keep the form populated after an error:
export const signIn = createServerAction<typeof schema>(
schema,
async () => {
return { ok: false, message: "Invalid credentials" };
},
{ clear: false }
);
By default, form values are cleared when an error occurs. This helps reset the form unless you explicitly disable it.
Middleware Handling
If you've defined a global middleware in createClient
, and it returns a message:
middleware: async () => {
return { message: "Unauthorized access" };
}
Then this message will be returned by any server action, and the handler won't be executed:
{
ok: false,
message: "Unauthorized access",
values: {} // or original values if clear: false
}