Skip to content

m6io/react-formgen

Repository files navigation

React FormGen

A headless, type-safe, customizable, and super simple React form generator. Turn your schemas into forms with ease.

Quick Links

@react-formgen/core - Core architecture for building schema-based form generators in React (npmsource)

@react-formgen/json-schema - JSON Schema implementation for react-formgen (npmsource)

@react-formgen/yup - Yup schema implementation for react-formgen (npmsource)

@react-formgen/zod - Zod schema implementation for react-formgen (npmsource)

Motivation

Forms are not fun to write. They are repetitive, error-prone, and time-consuming. This library aims to make form generation as simple as possible.

The packages in this repository are designed to be un-opinionated, flexible, modular, and highly customizable.

There are two types of packages in this repository:

  1. Core package: This package (@react-formgen/core) provides the core functionality for the schema-based packages. This package is not really meant to be used directly, but rather as a dependency for the schema-based packages. It serves as a "factory" for creating form providers and hooks that are schema-specific. Think of it as a "scaffolding" for the schema-based form generators.
  2. Schema-based packages: These packages take a schema (e.g., JSON Schema, Yup schema, Zod schema, etc.) and generate forms based on that schema. The schema-based packages are meant to be used directly in your projects.

How it Works

Take, for example, the JSON Schema package (@react-formgen/json-schema). This package takes a JSON Schema and generates a form based on that schema. The package provides a set of hooks and a provider that you can use in your components to generate forms and/or read-only data views.

Here's a visual representation of the core and schema-based package interaction:

flowchart LR
 subgraph JSONSchemaPackage["@react-formgen/json-schema"]
    direction LR
        JSONSchemaProvider["FormProvider"]
        JSONSchemaContext["useFormContext"]
        JSONSchemaDataAtPath["useFormDataAtPath"]
        JSONSchemaErrorsAtPath["useErrorsAtPath"]
        JSONSchemaArrayFieldset["useArrayTemplate"]
        JSONSchemaInitialData["generateInitialData (JSON Schema specific)"]
        JSONSchemaErrorsPath["getErrorsAtPath (JSON Schema specific)"]
        CoreProviderHooks["@react-formgen/core<br>createFormProviderAndHooks"]
        useRenderTemplate["useRenderTemplate"]
  end
 subgraph JSONSchemaFieldTemplates["Customized Templates"]
        ArrayFieldset["CustomArrayTemplate"]
        ObjectFieldset["CustomObjectTemplate"]
        BooleanField["CustomBooleanTemplate"]
        NumberField["CustomNumberTemplate"]
        StringField["CustomStringTemplate"]
  end
 subgraph JSONSchemaConsumers["App"]
    direction LR
        JSONSchemaFieldTemplates
        FormTemplate["CustomFormTemplate"]
        Form["Form"]
  end
    FormTemplate --- Form
    JSONSchemaFieldTemplates --- Form
    JSONSchemaPackage --- JSONSchemaConsumers
    JSONSchemaProvider --- Form
    useRenderTemplate --- ObjectFieldset & ArrayFieldset & FormTemplate
    JSONSchemaArrayFieldset --- ArrayFieldset
    JSONSchemaContext --- FormTemplate
    JSONSchemaDataAtPath --- StringField & BooleanField & NumberField
    JSONSchemaInitialData --- CoreProviderHooks
    JSONSchemaErrorsPath --- CoreProviderHooks
    CoreProviderHooks --- JSONSchemaContext & JSONSchemaProvider & JSONSchemaArrayFieldset & JSONSchemaErrorsAtPath & JSONSchemaDataAtPath
    JSONSchemaErrorsAtPath --- ObjectFieldset & BooleanField & NumberField & StringField




Loading

You can consume the JSON Schema package directly in your project, and customize the templates to suit your needs.

Customization

The schema-based packages are designed to be highly customizable. You can extend them by:

  • Customizing the Form Root Template (e.g., for custom form submission logic, root-level layout and beavior customization, etc.).
  • Customizing the Property Templates (e.g., how string, number, boolean, array, and object fields are rendered).
  • Overriding the Template Renderer (e.g., for customizing how schemas are parsed and rendered per subschema).

Available Packages

  • @react-formgen/core: Core package that provides the foundational form management logic.
  • @react-formgen/json-schema: JSON Schema-based form generator.
  • @react-formgen/yup-schema Yup-based form generator.
  • @react-formgen/zod-schema Zod-based form generator.

Key Features

  • Headless: No imposed UI or styling. You are free to define how the forms are rendered.
  • Type-safe: Strongly typed APIs and hooks that ensure schema and form data compatibility.
  • Customizable: Define your own templates for form fields and/or data views.
  • Unopinionated: The library does not enforce any specific schema validation library or approach, making it highly flexible.
  • Zustand for State Management: Leverages Zustand, a small, fast, and scalable state-management library.

Example

Here is a quick example of how to use the JSON Schema package to generate a form:

import React from "react";
import { Form } from "@react-formgen/json-schema";
import mySchema from "./mySchema.json";

const MyFormComponent = () => {
  const handleSubmit = (data) => {
    console.log("Form submitted with data:", data);
  };

  const handleErrors = (errors) => {
    console.error("Form submission errors:", errors);
  };

  return (
    <Form
      schema={mySchema}
      onSubmit={handleSubmit}
      onError={handleErrors}
      initialData={{}} // Optional initial form data
    />
  );
};

export default MyFormComponent;

Getting Started

  1. Install the schema package you want to use:
npm install @react-formgen/json-schema

or

yarn add @react-formgen/json-schema

or

pnpm add @react-formgen/json-schema
  1. Provide a JSON Schema to the Form component. You can do this by importing a JSON file, defining the schema directly in your component, fetching it from an API, etc.
import mySchema from "./mySchema.json";
  1. Use the Form component to generate a form based on the schema:
<Form schema={mySchema} onSubmit={handleSubmit} onError={handleErrors} />

For a read-only view, just pass the readonly prop to the Form component:

<Form schema={mySchema} readonly />

That's it! You now have a form generated based on your JSON Schema.

Obviously, this is a very basic example. You should customize the templates and to suit your needs.

Contributing

Contributions are welcome. Please open an issue or submit a pull request on the GitHub repository.

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

Headless, unopinionated, and flexible form generation.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published