1.5.1 • Published 9 months ago
server-act v1.5.1
Server-Act
A simple React server action builder that provides input validation.
You can use any validation library that supports Standard Schema.
Installation
# npm
npm install server-act zod
# yarn
yarn add server-act zod
# pnpm
pnpm add server-act zodUsage
// action.ts
"use server";
import { serverAct } from "server-act";
import { z } from "zod";
export const sayHelloAction = serverAct
  .input(
    z.object({
      name: z.string(),
    }),
  )
  .action(async ({ input }) => {
    return `Hello, ${input.name}`;
  });// client-component.tsx
"use client";
import { sayHelloAction } from "./action";
export const ClientComponent = () => {
  const onClick = () => {
    const message = await sayHelloAction({ name: "John" });
    console.log(message); // Hello, John
  };
  return (
    <div>
      <button onClick={onClick}>Trigger action</button>
    </div>
  );
};With Middleware
// action.ts
"use server";
import { serverAct } from "server-act";
import { z } from "zod";
export const sayHelloAction = serverAct
  .middleware(() => {
    const t = i18n();
    const userId = "..."
    return { t, userId };
  })
  .input((ctx) => {
    return z.object({
      name: z.string().min(1, { message: ctx.t("form.name.required") }),
    });
  })
  .action(async ({ ctx, input }) => {
    console.log("User ID", ctx.userId);
    return `Hello, ${input.name}`;
  });useActionState Support
useActionStateDocumentation:
We recommend using zod-form-data for input validation.
// action.ts;
"use server";
import { serverAct } from "server-act";
import { z } from "zod";
import { zfd } from "zod-form-data";
export const sayHelloAction = serverAct
  .input(
    zfd.formData({
      name: zfd.text(
        z
          .string({ required_error: `You haven't told me your name` })
          .max(20, { message: "Any shorter name? You name is too long 😬" }),
      ),
    }),
  )
  .formAction(async ({ formData, input, formErrors, ctx }) => {
    if (formErrors) {
      return { formData, formErrors: formErrors.fieldErrors };
    }
    return { message: `Hello, ${input.name}!` };
  });// client-component.tsx
"use client";
import { useActionState } from "react";
import { sayHelloAction } from "./action";
export const ClientComponent = () => {
  const [state, dispatch] = useFormState(sayHelloAction, undefined);
  return (
    <form action={dispatch}>
      <input
        name="name"
        required
        defaultValue={state?.formData?.get("name")?.toString()}
      />
      {state?.formErrors?.name?.map((error) => <p key={error}>{error}</p>)}
      <button type="submit">Submit</button>
      {!!state?.message && <p>{state.message}</p>}
    </form>
  );
};1.5.1
9 months ago
1.5.0
9 months ago
1.4.0
12 months ago
1.3.1
1 year ago
1.3.0
1 year ago
1.2.2
1 year ago
1.2.1
1 year ago
1.2.0
1 year ago
1.1.7
2 years ago
1.1.6
2 years ago
1.1.5
2 years ago
1.1.4
2 years ago
1.1.1
2 years ago
1.1.0
2 years ago
1.0.0
2 years ago
1.1.3
2 years ago
1.1.2
2 years ago
0.0.10
2 years ago
0.0.9
2 years ago
0.0.8
2 years ago
0.0.7
2 years ago
0.0.6
2 years ago
0.0.5
2 years ago
0.0.4
2 years ago
0.0.3
2 years ago
0.0.2
2 years ago
0.0.0
2 years ago
0.0.1
2 years ago