Skip to content

Releases: MiroslavPetrik/react-form-action

v.2.0.0 ActionContext API

23 Dec 16:55
f335b33
Compare
Choose a tag to compare
  • the action state is provided via the React context by the <Action> component and accessible by useActionContext()
  • <Form> is automatically contextual
  • ZodFieldError now is contextual as FieldError when created with the createComponents() handler.
  • new <Pending> component - better <FormStatus> which will be deprecated

v.1.3.0@next Action state in Form Context

19 Dec 14:35
Compare
Choose a tag to compare

New API:

  • New createForm helper to create form using <FormContext>
"use client";
import { createForm } from "react-form-action/client";
// The form renders the classic "render-props Form" and passes the state to FormContext
const { Form } = createForm(action);
  • New hook to access the state of the FormContext
import { useFormContext } from "react-form-action/client";

v1.1.0: Use `.format()` on zod error.

25 Sep 16:31
Compare
Choose a tag to compare

v.0.5.0: use .format() on zod error

25 Sep 16:39
Compare
Choose a tag to compare

support for react <18.3 which still uses the useFormState() from react-dom

v 1.0.1

11 Sep 13:06
Compare
Choose a tag to compare

React 18.3

typefix

06 Feb 11:15
Compare
Choose a tag to compare
  • fixes error data in the Form render prop

v0.4.1 bugfix

05 Feb 19:16
Compare
Choose a tag to compare

Fix passing the parseError of .error(parseError)

v.0.4.0 allow refinements in input

05 Feb 18:21
Compare
Choose a tag to compare

Schemas with refinement are now accepted in .input().
Refined schemas, or transformed schemas (with effects) are not augmentable, so only one .input() call will work for them.

"use server"
import { formAction } from "react-form-action";

export const signUp = formAction
  .input(
    z
      .object({
        email: z.string().email(),
        password: z.string(),
        confirm: z.string(),
      })
      .refine((data) => data.password === data.confirm, {
        message: "Passwords don't match",
        path: ["confirm"],
      })
  ) // if using refinement, only one input call is permited, as schema with ZodEffects is not extendable.
  .run(async ({ input: { email, password } }) => {
    // 🎉 passwords match!

    await db.signUp({ email, password });

    return "We've sent you an email!";
  });

v.0.3.0 Augmentative Input builder & internal form data parsing

05 Feb 11:43
Compare
Choose a tag to compare
"use server";
import { formAction } from "react-form-action";
import { z } from "zod";

const emailAction = formAction.input(z.object({ email: z.string() }));

const emailAndPassswordAction = emailAction.input(
  z.object({ password: z.string() })
);

// this is your server action, which accepts FormData
export const signUp = emailAndPassswordAction.run(
  async ({ input: { email, password } }) => {
    // do something with email and password
    await db.signUp(email, password);
  }
);

`formAction` builder with new `invalid` control state

03 Feb 19:59
Compare
Choose a tag to compare

react-form-action now supports a tRPC like API to build actions which share context middleware.
Moreover, the success and failure types were extended with an invalid type, which will appear in the form state alongside validationError which will contain error messages from zod schema validation.

"use server";

import { formAction } from "react-form-action";
import { z } from "zod";
import { cookies } from "next/headers";

const emailSchema = z.object({ email: z.string().email() });

const i18nMiddleware = async () => {
  const { t } = await useTranslation("auth", cookies().get("i18n")?.value);
  // will be added to context
  return { t };
};

// when the email will not be passed or will not be valid, the action
// will automatically fail with result {type: "invalid", validationError: {email: "Invalid"}}
const authAction = formAction(emailSchema)
  .use(i18nMiddleware)
  .use(async ({ ctx: { t } }) =>
    console.log("🎉 context enhanced by previous middlewares 🎉", t)
  )
  .error((error) => {
    if (error instanceof DbError) {
      return error.custom.code;
    } else {
      // unknown error
      // default Next.js error handling (error.js boundary)
      throw error;
    }
  });

export const resendVerifyEmailAction = authAction.run(
  async ({ ctx: { t }, input: { email } }) => {
    // do custom work
    await db.resendVerificationEmail({ email });

    // return translated success message
    return t("verificationEmail.success");
  }
);

export const sendResetPasswordEmail = authAction.run(
  async ({ ctx: { t }, input: { email } }) => {
    // do custom work
    await db.emailPasswordSendPasswordResetEmail({ email });

    // return translated success message
    return t("resetPasswordEmail.success");
  }
);