Provides convenient functions for both server and client to create and consume React Server Actions!
Table of Contents:
A Server Action can easily be created using the serverAction
function.
By using zod
an optional schema can be passed to validate incoming data.
"use server";
import {
ServerActionErr,
ServerActionOk,
} from "@wunderwerk/easy-server-actions";
import { serverAction } from "@wunderwerk/easy-server-actions/server";
import { z } from "zod";
// Payload schema.
const schema = z.object({
name: z.string(),
});
/**
* Server Action with input data.
*/
export const myAction = serverAction(schema, async (input) => {
const greeting = `Welcome ${input.name}!`
// Run your server code here!
// On error.
if (false) {
return ServerActionErr({
code: "some_error",
title: "Some Error",
detail: "An error occured whilst running the server action",
});
}
return ServerActionOk(greeting);
});
/**
* Server Action without input data.
*/
export const myActionWithoutSchema = serverAction(async () => {
// Run your server code here!
return ServerActionOk({
data: "some-data",
});
});
The return value of the server action must be either ServerActionErr
or ServerActionOk
.
The ServerActionOk
can contain any value, the signature of the error
must match the predefined type.
This package provides integration with @tanstack/react-query
to consume a
server action.
Use a server action to just fetch data.
By using the useServerActionQuery
react hook a server action can directly be
consumed and used like using useQuery
from @tanstack/react-query
.
This hook supports all the options as useQuery
.
More Info: TanStack Query useQuery
Docs.
"use client";
import { useServerActionQuery } from "@wunderwerk/easy-server-actions/client";
import { myAction } from "../some-path";
export function MyComponent() {
const { data, isLoading } = useServerActionQuery(myAction, {
queryKey: ["some-key"],
});
return <div />;
}
Similar to the hook above there is a custom variant for paginated data.
The useServerActionInfiniteQuery
react hook provides integration with
the useInfiniteQuery
hook from @tanstack/react-query
.
This hook supports all the options as useInfiniteQuery
.
More Info: TanStack Query useInfiniteQuery
Docs.
"use client";
import { useServerActionInfiniteQuery } from "@wunderwerk/easy-server-actions/client";
import { myAction } from "../some-path";
export function MyComponent() {
const { data, isLoading } = useServerActionInfiniteQuery(myAction, {
queryKey: ["some-key"],
prepareQueryFn(pageParam) {
// `pageParam` is the param coming from the `getNextPageParam` function.
// See `useInfiniteQuery` docs from TanStack Query for more info.
// Return the input object for the server action here.
return {};
},
});
return <div />;
}
Use a server action to post new data to the server.
The useServerAction
react hook can be used to achieve that.
An array with a dispatch function and a loading boolean is returned from the hook, success and error callbacks can be directly registered in the hook options.
"use client";
import { useServerAction } from "@wunderwerk/easy-server-actions/client";
import { myAction } from "../some-path";
export function MyComponent() {
const [dispatchAction, isPending] = useServerAction(myAction, {
onSuccess(greeting) {
alert(greeting);
},
onError(err) {
console.err(err);
alert(err.title);
},
});
const handleClick = async () {
const greeting = await dispatchAction({
name: "John Doe",
email: "john@doe.com",
});
// You have access to the success value here.
// Or you can skip the return value and just use
// the `onSuccess` callback.
// Similarily you can wrap the action call in a
// try/catch to get the error, or just use the
// `onError` callback.
};
return (
<div>
<button onClick={handleClick} disabled={isPending}>Dispatch</button>
</div>
);
}
Rules for ESLint to check React server actions usage / implementation.
Adds the following rules:
server-actions/consistent-export-name
If a file has "use server" declared at the top, any export MUST end withAction
.server-actions/consistent-file-name
If a file has "use server" declared at the top, the file MUST end withaction
. Supports kebab, pascal, camel and snakecase.server-actions/force-server-action-factory
Ensures that any export in file with top-level "use server" is using theserverAction
factory function.server-actions/no-export-default
Ensures that a file with top-level "use server" does not have a default export.server-actions/no-inline-use-server
Ensures that only top-level "use server" directives are used.
Just add the easy-server-actions
config to your eslint flat file config.
import serverActionsPlugin from "@wunderwerk/eslint-plugin-server-actions";
export default [
serverActionsPlugin.configs["easy-server-actions"],
];