Skip to content

christianjuth/better-react-server-actions

Folders and files

NameName
Last commit message
Last commit date
Sep 25, 2024
Sep 25, 2024
Sep 26, 2024
Sep 26, 2024
Sep 24, 2024
Sep 24, 2024
Sep 24, 2024
Sep 26, 2024
Sep 24, 2024
Sep 25, 2024
Sep 24, 2024
Sep 26, 2024

Repository files navigation

Getting Started

So you're like me and you love Server Actions, but you need more Zod and TypeScript!

Why Use This Library?

Why React 19+ is required

This library is designed to enhance useActionState, which requires React 19. Without that, you really won't get much benefit from this library.

I have only tested with Next.js for now, but the goal is to make this work with React in general.

Documentation

See christianjuth.github.io/better-react-server-actions.

Example

Login Form Example

"use server";
 
import { createActionWithState } from 'better-react-server-actions';
import { zfd } from 'zod-form-data';
import { z } from 'zod';
import { redirect } from 'next/navigation';
 
const EMAIL = '[email protected]';
const PASSWORD = 'password';
 
export const login = createActionWithState({
  formDataSchema: zfd.formData({
    email: z.string().email(),
    password: zfd.text(),
  }),
  requestHandler: async (prevState, { email, password }) => {
    if (email !== EMAIL || password !== PASSWORD) {
      throw new Error('Invalid email or password');
    }
 
    redirect('/examples/success')
  }
});
"use client";
 
import { useActionState } from 'react';
import { login } from './action';
 
export default function Page() {
  const [state, action] = useActionState(login, {});
 
  const formErrors = state.errors?.formErrors;
 
  return (
    <form action={action}>
      <h1>Login</h1>
 
      {state.errors?.actionErrors && (
        <span>
          {state.errors.actionErrors.join(', ')}
        </span>
      )}
 
      <label htmlFor="email">Email:</label>
      <input 
        id="email" 
        name="email" 
      />
      {formErrors?.email && (
        <span>
          {formErrors.email.join(', ')}
        </span>
      )}
 
      <label htmlFor="password">Password:</label>
      <input 
        id="password" 
        name="password" 
        type="password" 
      />
      {formErrors?.password && (
        <span>
          {formErrors.password.join(', ')}
        </span>
      )}
 
      <button>
        Login
      </button>
    </form>
  )
}

Like Button Example

"use server";
 
import { createActionWithState } from 'better-react-server-actions';
import { z } from 'zod';
 
export const login = createActionWithState({
  stateSchema: z.object({
    likeId: z.string().optional(),
  }),
  requestHandler: async ({ likeId }) => {
    // Check if user is logged in
    // and redirect to login page if not
 
    if (likeId) {
      // Delete like via api
      return {
        likeId: undefined,
      }
    } else {
      // Create like via api
      const newLikeId = 'new-like-id';
      return {
        likeId: newLikeId,
      }
    }
  }
});
"use client";
 
import { useActionState } from 'react';
import { toggleLike } from './action';
 
export default function Page() {
  const [state, action] = useActionState(toggleLike, {});
 
  return (
    <form action={action}>
      <button>
        {state.likeId ? 'Unlike' : 'Like'}
      </button>
    </form>
  )
}

Increment Counter Example

"use server";
 
import { createActionWithState } from 'better-react-server-actions';
import { z } from 'zod';
 
export const incrementCounter = createActionWithState({
  stateSchema: z.object({
    count: z.number().min(0),
  }),
  requestHandler: async ({ count }) => {
    return {
      count: count + 1,
    }
  }
});
"use client";
 
import { useActionState } from 'react';
import { incrementCounter } from './action';
 
export default function Page() {
  const [state, action] = useActionState(incrementCounter, {
    count: 0,
  });
 
  return (
    <form action={action}>
      <span>Count: {state.count}</span>
      <button>
        Increment
      </button>
    </form>
  )
}

About

A library to make React Server Actions better using Zod

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published