Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/chungweileong94/server-act

A simple React server action builder
https://github.com/chungweileong94/server-act

Last synced: about 1 month ago
JSON representation

A simple React server action builder

Awesome Lists containing this project

README

        

# Server-Act

[![npm version](https://badge.fury.io/js/server-act.svg)](https://badge.fury.io/js/server-act)

A simple React server action builder that provides input validation with zod.

## Installation

```bash
# npm
npm install server-act zod

# yarn
yarn add server-act zod

# pnpm
pnpm add server-act zod
```

## Usage

```ts
// 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}`;
});
```

```tsx
// 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 (


Trigger action

);
};
```

### With Middleware

```ts
// action.ts
"use server";

import { serverAct } from "server-act";
import { z } from "zod";

export const sayHelloAction = serverAct
.middleware(() => {
const userId = "...";
return { userId };
})
.input(
z.object({
name: z.string(),
}),
)
.action(async ({ ctx, input }) => {
console.log("User ID", ctx.userId);
return `Hello, ${input.name}`;
});
```

### `useActionState` Support

> `useActionState` Documentation:
>
> - https://react.dev/reference/react/useActionState

We recommend using [zod-form-data](https://www.npmjs.com/package/zod-form-data) for input validation.

```ts
// 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.formErrors.fieldErrors };
}
return { message: `Hello, ${input.name}!` };
});
```

```tsx
// client-component.tsx
"use client";

import { useActionState } from "react";
import { sayHelloAction } from "./action";

export const ClientComponent = () => {
const [state, dispatch] = useFormState(sayHelloAction, undefined);

return (


{state?.formErrors?.name?.map((error) =>

{error}

)}

Submit

{!!state?.message &&

{state.message}

}

);
};
```