惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
小众软件
小众软件
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
宝玉的分享
宝玉的分享
有赞技术团队
有赞技术团队
J
Java Code Geeks
WordPress大学
WordPress大学
The Cloudflare Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Building Dynamic Forms in React + Formik Using JSON Confi...
Shivani R · 2026-05-24 · via DEV Community

Recently, I started working on building a dynamic form system using React + Formik where the entire form UI was driven by JSON configuration instead of hardcoded components.

Instead of manually writing fields like this:

I wanted the frontend to dynamically render forms based on configuration received from the backend.

This is the beginning of a blog series where I’ll cover:

  • dynamic form rendering
  • layout handling
  • dynamic Yup validation schemas
  • conditional child fields
  • API-driven dropdowns
  • multi-step forms
  • nested field handling

Starting with the foundation: rendering forms dynamically from JSON.


🧠 Why Dynamic Forms?

Static forms work fine initially.

But as forms become:

  • configurable
  • reusable
  • API-driven
  • multi-step

hardcoding fields becomes difficult to maintain.

Dynamic forms help centralize:

  • field structure
  • UI layout
  • validation metadata
  • rendering logic

inside configuration itself.


📦 Form Configuration Structure

I started with a grouped schema structure like this:

export const formConfig = {
   "personalDetails":[
      {
         "colWidth":4,
         "field":"firstName",
         "label":"First Name",
         "type":"text"
      },
      {
         "colWidth":4,
         "field":"middleName",
         "label":"Middle Name",
         "type":"text"
      },
      {
         "colWidth":4,
         "field":"lastName",
         "label":"Last Name",
         "type":"text"
      }
   ],
   "contactDetails":[
      {
         "colWidth":6,
         "field":"email",
         "label":"Email",
         "type":"email"
      },
      {
         "colWidth":6,
         "field":"phone",
         "label":"Phone Number",
         "type":"text"
      }
   ],
   "addressDetails":[
      {
         "colWidth":12,
         "field":"address",
         "label":"Address",
         "type":"text",
         "customClass":"mb-3"
      }
   ]
}

Enter fullscreen mode Exit fullscreen mode


📐 Handling Dynamic Layout Positioning

Different forms may require:

  • multiple fields per row
  • full-width sections
  • responsive layouts
  • custom spacing

Instead of hardcoding Bootstrap grid classes inside components, I added layout properties directly into the schema:

{
  colWidth: 6,
  field: 'email',
  label: 'Email',
  type: 'email',
}

Enter fullscreen mode Exit fullscreen mode

This allowed the renderer to dynamically decide:

  • how many fields appear per row
  • how much width each field occupies

⚙️ Rendering the Form Dynamically

The renderer loops through grouped sections using Object.entries() and renders fields dynamically.

const DynamicFormRenderer = ({ schema }) => {
    return (
        <>
            {Object.entries(schema)?.map(([sectionTitle, fields], index) => (
                <div
                    key={index}
                    className='border rounded p-4 mb-4'>
                    <h3 className='mb-3 text-capitalize'> {sectionTitle} </h3>
                    <div className='row'>
                        {fields?.map((field, index) => {
                            const { colWidth, customClass } = field;
                            return (
                                <div
                                    key={index}
                                    className={`col-md-${colWidth} ${customClass || ''}`}>
                                    {renderInputField(field)}
                                </div>
                            );
                        })}
                    </div>
                </div>
            ))}
        </>
    );
};


Enter fullscreen mode Exit fullscreen mode


🧩 Dynamic Field Rendering

Field rendering is handled through a centralized mapper function.

const renderInputField = (field) => {
    const { type, label, options, field: fieldName } = field;
    switch (type) {
        case 'select':
            return (
                <CustomSelect
                    label={label}
                    options={options}
                    name={fieldName}
                />
            );
        default:
            return (
                <CustomInput
                    label={label}
                    name={fieldName}
                    type={type}
                />
            );
    }
};

Enter fullscreen mode Exit fullscreen mode

This keeps rendering logic scalable as more field types are introduced later.


🏗️ Generating Initial Values Dynamically

Since fields are configuration-driven, initial values also need to be generated dynamically.

export const buildInitialValues = (schema) => {
    const initialValues = {};
    Object.values(schema).forEach((fields) => {
        fields.forEach((field) => {
            initialValues[field.field] = field.initialValue ?? '';
        });
    });
    return initialValues;
};

Enter fullscreen mode Exit fullscreen mode

This helps avoid manually maintaining large initial value objects.


✅ Benefits of This Approach

Reusability

The same renderer can support multiple forms.

Easier Maintenance

Adding fields becomes a config update instead of component rewrites.

Backend-Driven UI

Frontend becomes more flexible for enterprise workflows.

Scalable Architecture

This structure becomes extremely useful once:

  • validations
  • child fields
  • API dropdowns
  • multi-step flows

start getting introduced.


⚠️ Challenges That Appear Later

Dynamic rendering is actually the easy part.

The real complexity starts when handling:

  • dynamic Yup schemas
  • conditional child fields
  • dependent dropdown APIs
  • nested arrays
  • performance optimization
  • step-wise validation

That’s where architecture decisions start becoming important.


🚀 Next Part

In the next part of this series, I’ll cover:
👉 generating dynamic Yup validation schemas from JSON configuration using React + Formik.

That turned out to be much more interesting than the rendering itself.