DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide
  • Mastering React App Configuration With Webpack
  • Overcoming React Development Hurdles: A Guide for Developers

Trending

  • Testing SingleStore's MCP Server
  • Event-Driven Architectures: Designing Scalable and Resilient Cloud Solutions
  • How to Convert XLS to XLSX in Java
  • Unlocking the Potential of Apache Iceberg: A Comprehensive Analysis
  1. DZone
  2. Coding
  3. JavaScript
  4. Dynamic Web Forms In React For Enterprise Platforms

Dynamic Web Forms In React For Enterprise Platforms

With JSON-based dynamic forms in React, you can achieve seamless integration with APIs and ensure consistency throughout the project.

By 
Anant Wairagade user avatar
Anant Wairagade
·
Apr. 04, 25 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
7.0K Views

Join the DZone community and get the full member experience.

Join For Free

Forms are some of the easiest things to build in React, thanks to the useForm hook. For simple forms such as login, contact us, and newsletter signup forms, hard coding works just fine. But, when you have apps that require frequent updates to their forms, for example, surveys or product configuration tools, hard coding becomes cumbersome.

The same goes for forms that require consistent validation or forms in apps that use micro frontends. For these types of forms, you need to build them dynamically. Fortunately, JSON and APIs provide a straightforward way to define and render these types of forms dynamically.

In this guide, we’ll go over how you can use JSON and APIs (REST endpoints) to do this and how to set up a UI form as a service. Let’s start with creating dynamic forms based on JSON.

Dynamic Forms in React Based on JSON

What are Dynamic Forms in React?

In React, dynamic forms based on JSON are forms where the structure (fields, labels, validation rules, etc.) is generated at runtime based on a JSON configuration. This means you don’t hard-code the form fields, labels, etc. Instead, you define all of this information in a JSON file and render your form based on the JSON file’s content.

Here’s how this works:

  • You start by defining your JSON schema. This will be your form’s blueprint. In this schema, you define the input field types (text, email, checkboxes, etc.), field labels and placeholders, whether the fields are required, and so on, like below:
    JSON
     
    {
      "title": "User Registration",
      "fields": [
        {
          "name": "fullName",
          "label": "Full Name",
          "type": "text",
          "placeholder": "Enter your full name",
          "required": true
        },
        {
          "name": "email",
          "label": "Email Address",
          "type": "email",
          "placeholder": "Enter your email",
          "required": true
        },
        {
          "name": "gender",
          "label": "Gender",
          "type": "select",
          "options": ["Male", "Female", "Other"],
          "required": true
        },
        {
          "name": "subscribe",
          "label": "Subscribe to Newsletter",
          "type": "checkbox",
          "required": false
        }
      ]
    }
  • Create a form component (preferably in Typescript).
  • Import your JSON schema into your component and map over it to create and render the form dynamically.

Note: When looking into dynamic forms in React, you will likely come across them as forms where users can add or remove fields based on their needs. For example, if you’re collecting user phone numbers, they can choose to add alternative phone numbers or remove these fields entirely. 

This is a feature you can hard-code into your forms using the useFieldArray hook inside react-hook-form.


But in our case, we refer to the dynamic forms whose renders are dictated by the data passed from JSON schema to the component. 

Why Do We Need Dynamic Forms?

The need for dynamic forms stems from the shortcomings of static forms. These are the ones you hard-code, and if you need to change anything in the forms, you have to change the code. But dynamic forms are the exact opposite.

Unlike static forms, dynamic forms are flexible, reusable, and easier to maintain. Let’s break these qualities down:

  • Flexibility. Dynamic forms are easier to modify. Adding or removing fields is as easy as updating the JSON scheme. You don’t have to change the code responsible for your components.
  • One form, many uses. One of React’s key benefits is how its components are reusable. With dynamic forms, you can take this further and have your forms reusable in the same way. You have one form component and reuse it for different use cases.

For example, create one form but with a different schema for admins, employees, and customers on an e-commerce site.

  • Custom, consistent validation. You also define the required fields, regex patterns (for example, if you want to validate email address formats), and so on in JSON. This ensures that all forms follow the same validation logic.

These features make dynamic forms ideal for enterprise platforms where forms are complex and need constant updates.

Why JSON for Dynamic Forms?

JSON (short for Javascript Object Notation) is ideal for defining dynamic forms. Its readability, compatibility, and simplicity make it the best option to easily manipulate, store, and transmit dynamic forms in React. You can achieve seamless integration with APIs and various systems by representing form structures as JSON.

With that in mind, we can now go over how to build dynamic forms in React with JSON.

Building Dynamic Forms in React With JSON

JSON Structure for Dynamic Forms

The well-structured JSON schema is the key to a highly useful dynamic form. A typical JSON structure looks as follows:

JSON
 
{
  "title": "Registration",
  "fields": [
    {
      "fieldType": "text",
      "label": "First Name",
      "name": "First_Name",
      "placeholder": "Enter your first name",
      "validationRules": {
        "required": true,
        "minLength": 3
      }
    },
    {
      "fieldType": "text",
      "label": "Last Name",
      "name": "Last_Name",
      "placeholder": "Enter your Last Name",
      "validationRules": {
        "required": true,
        "minLength": 3
      }
    },
    {
      "fieldType": "email",
      "label": "Email",
      "name": "email",
      "placeholder": "Enter your email",
      "validationRules": {
        "required": true,
        "pattern": "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$"
      }
    },
    {
      "fieldType": "text",
      "label": "Username",
      "name": "username",
      "placeholder": "Enter your username",
      "validationRules": {
        "required": true,
        "minLength": 3
      }
    },
    {
      "fieldType": "select",
      "label": "User Role",
      "name": "role",
      "options": ["User", "Admin"],
      "validationRules": {
        "required": true
      }
    }
  ],
  "_comment": "Add more fields here."
}


 Save the above code as formSchema.JSON.

Now that we have the JSON schema, it's time to implement and integrate it into the React form.

Implementing JSON Schema in React Dynamic Forms

Here is a comprehensive guide for implementing dynamic forms in React.

Step 1: Create React Project

Run the following script to create a React project:

Plain Text
 
npx create-react-app dynamic-form-app
cd dynamic-form-app


After creating your React app, start by installing the React Hook Form this way:

Plain Text
 
npm install react-hook-form


Then, destructure the useForm custom hook from it at the top. This will help you to manage the form’s state. 

Step 2: Render the Form Dynamically

Create a React Dynamic Forms component and map it through the JSON schema by importing it.

JavaScript
 
import React from 'react';
import { useForm } from 'react-hook-form';
import formSchema from './formSchema.json';

const DynamicForm = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const onSubmit = (data) => {
    console.log('Form Data:', data);
  };

  const renderField = (field) => {
    const {
      fieldType,
      label,
      name,
      placeholder,
      options,
      validationRules
    } = field;

    switch (fieldType) {
      case 'text':
      case 'email':
        return (
          <div key={name} className="form-group">
            <label>{label}</label>
            <input
              type={fieldType}
              name={name}
              placeholder={placeholder}
              {...register(name, validationRules)}
              className="form-control"
            />
            {errors[name] && (
              <p className="error">{errors[name].message}</p>
            )}
          </div>
        );

      case 'select':
        return (
          <div key={name} className="form-group">
            <label>{label}</label>
            <select
              name={name}
              {...register(name, validationRules)}
              className="form-control"
            >
              <option value="">Select...</option>
              {options.map((option) => (
                <option key={option} value={option}>
                  {option}
                </option>
              ))}
            </select>
            {errors[name] && (
              <p className="error">{errors[name].message}</p>
            )}
          </div>
        );

      default:
        return null;
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="dynamic-form">
      <h2>{formSchema.title}</h2>
      {formSchema.fields.map((field) => renderField(field))}
      <button type="submit" className="btn btn-primary">
        Submit
      </button>
    </form>
  );
};

export default DynamicForm;


Please note that you must handle different input types in dynamic forms with individual cases. Each case handles a different data type:

JavaScript
 
const renderField = (field) => {
  switch (field.type) {
    case 'text':
    case 'email':
    case 'password':
      // ... other cases ...
      break;
    default:
      return <div>Unsupported field type</div>;
  }
};


Step 3: Submit the Form

When the form is submitted, the handleSubmit function processes the data and sends it to the API and the state management system.

JavaScript
 
const onSubmit = (data) => {
  // Process form data
  console.log('Form Data:', data);

  // Example: Send to API
  // axios.post('/api/register', data)
  //   .then(response => {
  //     // Handle success
  //   })
  //   .catch(error => {
  //     // Handle error
  //   });
};


So that’s how you can create dynamic forms using JSON to use in your React app. Remember that you can integrate this form component in different pages or different sections of a page in your app.

But, what if you wanted to take this further? By this, we mean having a dynamic form that you can reuse across different React apps. For this, you’ll need to set up a UI form as a service.

Setting Up Your Dynamic Form as a UI Form as a Service

First things first, what is a UI form as a service? This is a solution that allows you to render dynamic forms by fetching the form definition from a backend service. It is similar to what we’ve done previously.

Only here, you don’t write the JSON schema yourself — this is provided by a backend service. This way, anytime you want to render a dynamic form, you just call a REST endpoint, which returns the UI form component ready to render.

How This Works

If you want to fetch a REST API and dynamically render a form, here’s how you can structure your project:

  1. Set up a backend service that provides the JSON schema.
  2. The frontend fetches the JSON schema by calling the API.
  3. Your component creates a micro frontend to render the dynamic form. It maps over the schema to create the form fields.
  4. React hook form handles state and validation.

Step 1: Set Up a Back-End Service That Provides JSON Schema

There are two ways to do this, depending on how much control you want:

  • You can build your own API using Node.j, Django, or Laravel. Here’s an example of what this might look like with Node.js and Express backend.
JavaScript
 
const express = require("express");
const cors = require("cors");

const app = express();
app.use(cors()); // Enable CORS for frontend requests

// API endpoint that serves a form schema
app.get("/api/form", (req, res) => {
  res.json({
    title: "User Registration",
    fields: [
      {
        name: "username",
        label: "Username",
        type: "text",
        required: true
      },
      {
        name: "email",
        label: "Email",
        type: "email",
        required: true
      },
      {
        name: "password",
        label: "Password",
        type: "password",
        required: true,
        minLength: 8
      },
      {
        name: "age",
        label: "Age",
        type: "number",
        required: false
      },
      {
        name: "gender",
        label: "Gender",
        type: "select",
        options: ["Male", "Female", "Other"],
        required: true
      }
    ]
  });
});

app.listen(5000, () => console.log("Server running on port 5000"));


To run this, you’ll save it as sever.js, install dependencies (express CORS), and finally run node server.js. Now, your react frontend can call http://localhost:5000/api/form to get the form schema.

  • If you don’t want to build your own backend, you can use a database service, such as Firebase Firestore, that provides APIs for structured JSON responses. 

If you just want to test this process you can use mock APIs from JSON Placeholder. This is a great example of an API you can use: https://jsonplaceholder.typicode.com/users.

Step 2: Create Your Dynamic Form Component

You’ll create a typical React component in your project. Ensure to destructure the useEffect and useForm hooks to help in handling side effects and the form’s state, respectively. 

JavaScript
 
import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";

const DynamicForm = ({ apiUrl }) => {
  const [formSchema, setFormSchema] = useState(null);
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm();

  // Fetch form schema from API
  useEffect(() => {
    fetch(apiUrl)
      .then((response) => response.json())
      .then((data) => setFormSchema(data))
      .catch((error) => console.error("Error fetching form schema:", error));
  }, [apiUrl]);

  const onSubmit = (data) => {
    console.log("Submitted Data:", data);
  };

  if (!formSchema) return <p>Loading form...</p>;

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <h2>{formSchema.title}</h2>

      {formSchema.fields.map((field) => (
        <div key={field.name}>
          <label>{field.label}:</label>
          {field.type === "select" ? (
            <select
              {...register(field.name, {
                required: field.required
              })}
            >
              <option value="">Select</option>
              {field.options.map((option) => (
                <option key={option} value={option}>
                  {option}
                </option>
              ))}
            </select>
          ) : (
            <input
              type={field.type}
              {...register(field.name, {
                required: field.required,
                minLength: field.minLength
              })}
            />
          )}
          {errors[field.name] && <p>{field.label} is required</p>}
        </div>
      ))}

      <button type="submit">Submit</button>
    </form>
  );
};

export default DynamicForm;


This form will fetch the schema from the API and generate fields dynamically based on it. React hook form will handle state management and validation.

Step 3: Use the Form Component in Your App

This step is quite easy. All you have to do is pass the API endpoint URL as a prop to the dynamic form component.

JavaScript
 
import React from "react";
import DynamicForm from "./DynamicForm";

const App = () => {
  return (
    <div>
      <h1>Form as a Service</h1>
      <DynamicForm apiUrl="https://example.com/api/form" />
    </div>
  );
};

export default App;


React will create a micro-frontend and render the form on the frontend.

Why Would You Want to Use This?

As mentioned earlier, a UI form as a service is reusable, not only across different pages/page sections of your app, but also across different apps. You can pass the REST endpoint URL as a prop in a component of another app.

What’s more, it keeps your application lean. You manage your forms centrally, away from your main application. This can have some significant performance advantages.

Advantages and Limitations of Dynamic Forms

Advantages

  • Reduced redundant code enables developers to manage and handle complex forms conveniently.
  • Dynamic forms are easier to update, as changing the JSON schema automatically updates the form.
  • JSON schemas can be reused across different parts of the application. You can take this further with a UI form as a service that is reusable across different applications.
  • Dynamic forms can handle the increased complexity as the application scales. 

Limitations

  • Writing validation rules for multiple fields and external data can be cumbersome. Also, if you want more control with a UI form as a service, you’ll need to set up a custom backend, which in itself is quite complex.
  • Large or highly dynamic forms affect the performance of the application. With the first method where you’re creating your own JSON file, you still have to write a lot of code for each form field.
  • Finding and resolving bugs and errors in dynamically generated forms can be challenging.

Bonus: Best Practices for Dynamic Forms in React

On their own, dynamic forms offer many advantages. But to get the best out of them, you’ll need to implement the following best practices.

Modular Programming

Divide the rendering logic into modules for better navigation and enhanced reusability. This also helps reduce the code complexity. This is something you easily achieve with a UI form as a service. It decouples the form’s logic from your application logic. In the event that one of the two breaks down, the other won’t be affected.

Use the Validation Library

It is best to use a validation library to streamline the process for complex validation rules. This will abstract you from writing validation rules for every possible scenario you can think of.

Extensive Testing

Test your dynamic forms extensively to cover all possible user inputs and scenarios. Include various field types, validation rules, and submission behaviors to avoid unexpected issues.

Performance Optimization

As mentioned earlier, the increased dynamicity affects the application's performance. Therefore, it is crucial that you optimize the performance by implementing components like memoization, lazy loading, and minimizing the re-renders.

Define Clear and Consistent JSON Schemas

Stick to a standard structure for defining all the JSON schemas to ensure consistency and enhance maintainability. Moreover, clear documentation and schema validation can also help prevent unexpected errors and faults. Furthermore, it aids team collaboration.

With these best practices, you can achieve highly robust, efficient, and maintainable dynamic forms in React with JSON.

Conclusion

Dynamic forms in React based on JSON serve as a powerful tool for designing flexible user interfaces. By defining the form structure in JSON schemas, you can streamline form creation and submission dynamically. Moreover, this helps enhance the maintainability and adaptability of the application. Although this process has a few limitations, the benefits heavily outweigh them.

In addition, you can work around some of the limitations by using the UI form as a service. This solution allows you to manage your dynamic forms independently of your application. Because of this, you can reuse these forms across multiple apps.

With JSON-based dynamic forms, you can achieve seamless integration with APIs and ensure consistency throughout the project. 

JSON JavaScript Form (document) React (JavaScript library)

Opinions expressed by DZone contributors are their own.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide
  • Mastering React App Configuration With Webpack
  • Overcoming React Development Hurdles: A Guide for Developers

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!