How to Build Forms Dynamically in React/Redux?

Written by oleg2014 | Published 2018/06/01
Tech Story Tags: react | redux | forms

TLDRvia the TL;DR App

A step-by-step guide with demo and source code

You will not surprise anybody these days with splitting long forms into multi-step wizards, live client-side validation, initializing data and making sections/fields visibile depending on other fields. It is ‘must-have’ now. Otherwise, using complicated forms feels awkward and painful. In ProductCrafters we use Redux for state-management, so it’s logical to choose the best package for the form management. Redux-Form (~10k stars on GitHub) contains all listed features and a lot more, like tools for normalizing data, the array of fields and much more. After using it more than 2 years we are very happy with it.

We are facing client requirement to have partly or even 100% dynamic form. We get such a request from our fintech app customer. Recently, we’ve got a similar request for a heathlcare app. Meaning, form structure and validation rules will be fetched from the server; based on these data form (or wizard) should be created without making any changes on the client side. In this article, I want to share own experience of building such dynamic form wizard.

Here is the demo:

Step 1: Render a single dynamic field

Here is the usual way to render field in Redux-Form:

We need to specify the field name, and a single component that should render it (input, checkbox, select, etc), the label is optional, but I like to have single component that can both describe a field and show it.

To get started, I have created sample server response mock, to render this field:

To simplify this tutorial I will cut fetching data and parsing JSON. We will use mock as it would look like after parsing.

Using this data to feed the <Field> gonna give us fully-functional input.

In code above I do not use standard HTML5 <input />. There are custom created components. And stringToComponentMapper helps to choose correct component using key from json data. If you have never worked with redux-form before, just use default HTML 5 elements: “input”, “checkbox”, “select”.

Step 2: Create Dynamic Sections

Redux-form has a cool feature — FormSection. It allows to group together common fields for one entity.

The _FormSection_ component makes it easy to split forms into smaller components that are reusable across multiple forms. It does this by prefixing the name of _Field_, _Fields_ and _FieldArray_ children, at any depth, with the value specified in the _name_ prop.

Here what we had to write before it:

With <FormSection />:

I made some changes to mock data, extracted section object with own name and moved previous content inside fields:

Now we may easily render form section. FormGenerator receives data via prop and loops over it. Then each section loops over its fields.

It makes sense to extract SectionList and SectionRenderer components to avoid code in jsx. I have not done it here to make code shorter and focus on dynamic UI.

Step 3: Dynamic Form Wizard

Let’s make a change to the previous mock:

Now let’s add 2 files:

WizardProdiver.js — will remember current wizard page and manage page change. In this example, I also experiment with latest React Context, if it’s new for you, read official docs.

And PageTemplate.js will use FormGenerator and create a form around it:

Finally, we are wrapping everything together in Wizard.js:

Sample code:

ProductCrafters/Dynamic-Redux-Form-Wizard_Contribute to Dynamic-Redux-Form-Wizard development by creating an account on GitHub._github.com

Here is a demo.

In repo for this article, you may find simple regex validation also. This is very basic dynamic form. In real projects, we have much harder requirements, for example, dynamic rules for visibility of particular fields or section. It may be a topic for the second part of this article :)

P.S. 🚀My team uses React/React Native to build production apps over 3 years. We help US startup founders to bring their ideas to life. Need help with your project? ✉️ [email protected]


Published by HackerNoon on 2018/06/01