iway1 / react-ts-form

https://react-ts-form.com
MIT License
2.01k stars 33 forks source link

banner

Build maintainable, typesafe forms faster ๐Ÿƒ๐Ÿ’จ

@ts-react/form handles the boilerplate involved when building forms using zod and react-hook-form without sacrificing customizability.

[![codecov](https://codecov.io/github/iway1/react-ts-form/branch/main/graph/badge.svg?token=U4UFRGI3HF)](https://codecov.io/github/iway1/react-ts-form) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/isaac_ts_way.svg?style=social&label=Follow%20%40isaac_ts_way)](https://twitter.com/isaac_ts_way)

Features

Docs

Input Field Examples

Quick Start

Installation

Make sure you have "strict": true in your tsconfig.json compilerOptions and make sure you set your editors typescript version to v4.9 (or intellisense won't be as reliable).

Install package and dependencies with your preferred package manager:

yarn add @ts-react/form

# required peer dependencies
yarn add zod react-hook-form @hookform/resolvers

Usage

Create a zod-to-component mapping to map zod schemas to your components then create your form with createTsForm (typically once per project):

// create the mapping
const mapping = [
  [z.string(), TextField],
  [z.boolean(), CheckBoxField],
  [z.number(), NumberField],
] as const; // ๐Ÿ‘ˆ `as const` is necessary

// A typesafe React component
const MyForm = createTsForm(mapping);

Now just create form schemas with zod and pass them to your form:

const SignUpSchema = z.object({
  email: z.string().email("Enter a real email please."), // renders TextField
  password: z.string(),
  address: z.string(),
  favoriteColor: z.enum(["blue", "red", "purple"]), // renders DropDownSelect and passed the enum values
  isOver18: z.boolean(), // renders CheckBoxField
});

function MyPage() {
  function onSubmit(data: z.infer<typeof SignUpSchema>) {
    // gets typesafe data when form is submitted
  }

  return (
    <MyForm
      schema={SignUpSchema}
      onSubmit={onSubmit}
      renderAfter={() => <button type="submit">Submit</button>}
      // optional typesafe props forwarded to your components
      props={{
        email: {
          className: "mt-2",
        },
      }}
    />
  );
}

That's it! Adding a new field to your form just means adding an additional property to the schema.

It's recommended but not required that you create a custom form component to handle repetitive stuff (like rendering the submit button).

Full Documentation

You can read the full docs here

TypeScript versions

Older versions of typescript have worse intellisense and may not show an error in your editor. Make sure your editors typescript version is set to v4.9 plus. The easiest approach is to upgrade your typescript globally if you haven't recently:

sudo npm -g upgrade typescript

Or, in VSCode you can do (Command + Shift + P) and search for "Select Typescript Version" to change your editors Typescript Version:

Screenshot 2023-01-01 at 10 55 11 AM

Note that you can still compile with older versions of typescript and the type checking will work.

Limitations