1.5.1 • Published 4 months ago

server-act v1.5.1

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

Server-Act

npm version

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 zod

Usage

// 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

useActionState Documentation:

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

4 months ago

1.5.0

4 months ago

1.4.0

7 months ago

1.3.1

8 months ago

1.3.0

8 months ago

1.2.2

11 months ago

1.2.1

11 months ago

1.2.0

1 year ago

1.1.7

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.4

1 year 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