20 January 2025

Formity: The Ultimate Tool For Multi-Step Forms In React

As a frontend developer, you've likely faced the challenge of creating multi-step forms. These forms can be tricky to build, especially when they must adapt dynamically to user responses. Formity is designed to simplify this process, filling the gap left by existing form libraries.

Tell us about yourself

We would want to know a little bit more about you

The Problem With Existing Form Libraries

There are many great form libraries available, such as React Hook Form, Formik, and Tanstack Form, which excel at handling single-step forms efficiently. However, these form libraries lack built-in solutions for managing multi-step navigation and advanced logic. For instance, building an onboarding process or an interactive survey can be quite challenging with these tools.

This is where Formity steps in - a library to address the complexities of multi-step forms, offering developers the tools they need to create forms that are both dynamic and scalable.

Key Features of Formity

Formity provides a range of features that make it the go-to tool for creating advanced forms.

Advanced Logic

You can add sophisticated logic to your multi-step forms using features such as conditions, loops, and variables. This enables you to create truly dynamic forms where the flow adapts to user input.

Integration With Any Form Library

Formity doesn't force you to abandon your favorite form library. You can seamlessly integrate it with libraries like React Hook Form, Formik, or any other form-handling tool.

Advanced Type Inference

For TypeScript users, Formity offers advanced type inference to make the developer experience smooth and error-free. You'll get better autocomplete and improved type safety.

Type inference

How It Works

Formity's simplicity lies in its intuitive API. To create a multi-step form, you only need to:

  • Use the Formity component.

  • Create a schema that specifies the structure and behavior of the form.

Formity component

The Formity component is used to render the multi-step form.

import { useCallback, useState } from "react";

import { Formity, OnReturn, ReturnValues } from "@formity/react";

import { Data } from "@/components";

import { schema, Values } from "./schema";

export default function App() {
  const [values, setValues] = useState<ReturnValues<Values> | null>(null);

  const onReturn = useCallback<OnReturn<Values>>((values) => {
    setValues(values);
  }, []);

  if (values) {
    return <Data data={values} onStart={() => setValues(null)} />;
  }

  return <Formity<Values> schema={schema} onReturn={onReturn} />;
}

Form schema

The form schema is what defines the structure and behavior of the form.

export type Values = [
  // ...
];

export const schema: Schema<Values> = [
  {
    form: {
      values: () => ({
        working: [true, []],
      }),
      render: ({ values, ...rest }) => (
        <Controller step="working" {...rest}>
          <FormView
            defaultValues={values}
            resolver={zodResolver(
              z.object({
                working: z.boolean(),
              }),
            )}
          >
            <FormLayout
              heading="Are you currently working?"
              description="We would like to know if you are working for a company"
              fields={[<YesNo key="working" name="working" label="Working" />]}
              button={<Next>Next</Next>}
            />
          </FormView>
        </Controller>
      ),
    },
  },
  {
    cond: {
      if: ({ working }) => working,
      then: [
        {
          form: {
            values: () => ({
              company: ["", []],
            }),
            render: ({ values, ...rest }) => (
              <Controller step="company" {...rest}>
                <FormView
                  defaultValues={values}
                  resolver={zodResolver(
                    z.object({
                      company: z.string(),
                    }),
                  )}
                >
                  <FormLayout
                    heading="At what company?"
                    description="We would like to know the name of the company"
                    fields={[
                      <TextField
                        key="company"
                        name="company"
                        label="Company"
                      />,
                    ]}
                    button={<Next>Next</Next>}
                    back={<Back />}
                  />
                </FormView>
              </Controller>
            ),
          },
        },
        {
          return: ({ working, company }) => ({
            working,
            company,
          }),
        },
      ],
      else: [
        {
          form: {
            values: () => ({
              searching: [false, []],
            }),
            render: ({ values, ...rest }) => (
              <Controller step="searching" {...rest}>
                <FormView
                  defaultValues={values}
                  resolver={zodResolver(
                    z.object({
                      searching: z.boolean(),
                    }),
                  )}
                >
                  <FormLayout
                    heading="Are you looking for a job?"
                    description="If you are looking for a job, we would like to know"
                    fields={[
                      <YesNo
                        key="searching"
                        name="searching"
                        label="Searching"
                      />,
                    ]}
                    button={<Next>Next</Next>}
                    back={<Back />}
                  />
                </FormView>
              </Controller>
            ),
          },
        },
        {
          return: ({ working, searching }) => ({
            working,
            searching,
          }),
        },
      ],
    },
  },
];

Real-World Use Cases

Formity provides the flexibility to create applications that require dynamic, adaptive logic, making it ideal for handling complex workflows. Below we provide two practical examples.

Example #1: Quiz application

A quiz application that asks the user several questions and returns the number of correct answers.

What is the capital of Australia?

Choose the answer you think is correct.

SydneyMelbourneCanberra

Example #2: Fitness application

A fitness application that gives you workout routines based on your preferences and fitness goals.

What is your fitness goal?

We would like to know what is your fitness goal.

Why Choose Formity?

Formity excels at solving the complex challenges of multi-step forms. It provides developers with a powerful toolkit to design scalable, dynamic, and logic-driven solutions for a wide range of use cases, ensuring flexibility and ease of use.

So next time you're tasked with creating a multi-step form, give Formity a try. With its advanced logic capabilities, compatibility with popular form libraries, and robust TypeScript support, it empowers frontend developers to build dynamic and adaptive forms effortlessly.